[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='[0;31m' # Red.
+ grn='[0;32m' # Green.
+ lgn='[1;32m' # Light green.
+ blu='[1;34m' # Blue.
+ mgn='[0;35m' # Magenta.
+ std='[m' # 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, µ) ;
+
+ 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 (<ime);
++ _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> ¶m_int, KN<double> ¶m_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/&'/.,*(�&$$#!
#+&"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)'#!
$&: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,-,,Ġ/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> ¶m_int, KN<double> ¶m_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> ¶m_int,
+ KN<double> ¶m_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> ¶m_int,
+ KN<double> ¶m_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> ¶m_int, KN<double> ¶m_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> ¶m_int1,
+ const KN<double> ¶m_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> ¶m_int, const KN<double> ¶m_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> ¶m_int, KN<double> ¶m_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> ¶m_int, KN<double> ¶m_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> ¶m_int, const KN<double> ¶m_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> ¶m_int, KN<double> ¶m_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(<ime); // write the end time
+ now = localtime(<ime);
+ 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(<ime);
+ now = localtime(<ime);
+ 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(¤tWallTime, 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(¤tWallTime);
+ 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= ¶mmatElement_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= ¶mmatElement_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",°ree);
+ 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",°ree);
+
+ 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> ¶m_int,
+ KN<double> ¶m_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> ¶m_int,
+ KN<double> ¶m_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> ¶m_int, KN<double> ¶m_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> ¶m_int1, const KN<double> ¶m_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> ¶m_int, const KN<double> ¶m_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> ¶m_int, KN<double> ¶m_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> ¶m_int, const KN<double> ¶m_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> ¶m_int, KN<double> ¶m_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='[0;31m' # Red.
+ grn='[0;32m' # Green.
+ lgn='[1;32m' # Light green.
+ blu='[1;34m' # Blue.
+ mgn='[0;35m' # Magenta.
+ std='[m' # 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='[0;31m' # Red.
+ grn='[0;32m' # Green.
+ lgn='[1;32m' # Light green.
+ blu='[1;34m' # Blue.
+ mgn='[0;35m' # Magenta.
+ std='[m' # 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