[getfem] 01/05: Merge.

Anton Gladky gladk at alioth.debian.org
Sat Nov 2 20:16:58 UTC 2013


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

gladk pushed a commit to branch master
in repository getfem.

commit fa2b8720f2243b174780cc75dde06f24452f606c
Merge: b976502 c791f87
Author: Anton Gladky <gladky.anton at gmail.com>
Date:   Sat Nov 2 19:42:08 2013 +0100

    Merge.

 GNU_GCC_RUNTIME_EXCEPTION                          |   35 +
 GNU_GPL_V3                                         |  209 +
 GNU_LGPL_V3                                        |  105 +
 autogen.sh                                         |   31 +
 bin/ansys2getfem_mesh                              |  192 +
 bin/dr2dgnuplot                                    |   82 +
 bin/extract_doc                                    |  105 +-
 bin/fig2eps                                        |   76 +
 bin/file_dependencies                              |   42 +
 bin/makeheadfile                                   |  330 +
 bin/mesh_matlab_to_getfem                          |   62 +
 bin/rst_to_xml.py                                  |  175 +
 bin/sc2dgnuplot                                    |   77 +
 bin/test_dist                                      |   45 +
 bin/upload_documentation                           |   70 +
 bin/upload_html                                    |   71 +
 bin/upload_misc                                    |   71 +
 bin/upload_version                                 |   83 +
 bin/word_count                                     |   77 +
 configure.ac                                       | 1272 +
 configure.in                                       | 1200 -
 contrib/Makefile.am                                |    2 +-
 contrib/aposteriori/Makefile.am                    |    6 +-
 contrib/aposteriori/aposteriori.m                  |   46 +
 .../bimaterial_crack_test.param                    |    0
 contrib/bimat_contact_crack_test/Makefile.am       |    7 +-
 .../bimaterial_crack_test.m                        |   41 +
 contrib/bimaterial_crack_test/Makefile.am          |    7 +-
 .../bimaterial_crack_test/bimaterial_crack_test.cc |    6 +-
 .../bimaterial_crack_test/crack_exact_solution.cc  |    6 +-
 contrib/contact_grd_trans/Makefile.am              |    5 +-
 .../contact_continuation_load.param                |  119 +
 .../contact_continuation_time.param                |   95 +
 contrib/crack_plate/Makefile.am                    |    4 +-
 contrib/crack_plate/crack_bilaplacian_tools.cc     |    2 +-
 contrib/crack_plate/crack_panel.cc                 |  127 +
 contrib/crack_plate/crack_panel.param              |  139 +
 contrib/crack_plate/demi_plaque.mesh               |  242 +
 contrib/crack_plate/mortar_bilaplacian.h           |    2 +-
 contrib/crack_plate/serie.pl                       |  334 +
 contrib/delaminated_crack/Makefile.am              |    4 +-
 contrib/delaminated_crack/delaminated_crack.cc     |    4 +-
 contrib/icare/Makefile.am                          |    6 +-
 contrib/icare/icare.h                              |    2 +-
 contrib/icare/icareplot.m                          |   38 +
 contrib/icare/navier_stokes.net                    |  824 +
 contrib/icare/tralala_3D.geo                       |   81 +
 contrib/icare/tralala_3D.msh                       | 2492 +
 contrib/icare/triangular.msh                       | 3361 ++
 contrib/inter_element_test/Makefile.am             |    4 +-
 contrib/inter_element_test/square.msh              |  208 +
 contrib/inter_element_test/square_v1.msh           |  187 +
 contrib/level_set_contact/Makefile.am              |   21 +
 contrib/level_set_contact/contact_2D.param         |   53 +
 contrib/level_set_contact/contact_3D.param         |   56 +
 contrib/level_set_contact/contact_problem.cpp      |  116 +
 contrib/level_set_contact/contact_problem.h        |   24 +
 contrib/level_set_contact/contact_problem.pl       |   80 +
 contrib/level_set_contact/test_contact.cpp         |  174 +
 contrib/mixed_dynamic_friction/Makefile.am         |    4 +-
 .../mixed_dynamic_friction.m                       |  188 +
 .../mixed_scalar_hyperbolic.cfg                    |   38 +
 .../mixed_scalar_hyperbolic.m                      |  452 +
 .../mixed_scalar_hyperbolic_save.cfg               |   38 +
 .../mixed_scalar_hyperbolic_save.net               |  819 +
 contrib/mixed_dynamic_friction/util.py             |  121 +
 contrib/mixed_elastostatic/Makefile.am             |    4 +-
 contrib/static_contact_gears/Makefile.am           |    2 +-
 contrib/static_contact_gears/gear1.msh             | 5131 ++
 contrib/static_contact_gears/gear1_2D.msh          | 2674 ++
 contrib/static_contact_gears/gear1_2teeth.msh      | 9986 ++++
 contrib/static_contact_gears/gear2.msh             | 5131 ++
 contrib/static_contact_gears/gear2_2D.msh          | 2382 +
 contrib/static_contact_gears/gear2_2teeth.msh      | 9986 ++++
 .../static_contact_gears/static_contact_gears.cc   |  155 +-
 .../static_contact_gears.param                     |   35 +
 .../static_contact_gears_2D.param                  |   35 +
 .../static_contact_gears_2teeth.param              |   35 +
 .../static_contact_gears_u1_u2.cc                  |  212 +-
 .../static_contact_planetary.py                    |  353 +
 .../static_contact_planetary_1.msh                 | 4283 ++
 .../static_contact_planetary_2.msh                 | 7617 +++
 .../static_contact_planetary_3.msh                 | 4277 ++
 .../static_contact_planetary_4.msh                 | 4277 ++
 .../static_contact_planetary_5.msh                 | 4277 ++
 contrib/static_friction/Makefile.am                |    4 +-
 contrib/static_friction/ball_test.param            |   83 +
 contrib/static_friction/static_friction.cc         |    2 +-
 contrib/static_friction/static_friction.m          |  332 +
 contrib/tests_newton/punch2D_h1.mesh               | 2324 +
 contrib/tests_newton/punch2D_h4.mesh               |  168 +
 contrib/tests_newton/static_contact_1.m            |  536 +
 contrib/tests_newton/static_contact_2.m            |  536 +
 contrib/tests_newton/static_contact_3.m            |  537 +
 contrib/xfem_contact/Makefile.am                   |    4 +-
 contrib/xfem_contact/plot_xfem_dirichlet.m         |  519 +
 contrib/xfem_contact/xfem_dirichlet.cc             |    2 +-
 contrib/xfem_contact/xfem_stokes.cc                |    4 +
 contrib/xfem_large_strain/Makefile.am              |    4 +-
 .../compressible_getfem_nonlinear_elastoptim.h     |   20 +
 .../getfem_nonlinear_elastoptim.h                  |   22 +-
 contrib/xfem_large_strain/linear_incomp_xfem.param |   94 +
 contrib/xfem_stab_unilat_contact/Makefile.am       |    4 +-
 contrib/xfem_stab_unilat_contact/deformer.m        |   21 +
 .../xfem_stab_unilat_contact.cc                    |   57 +-
 .../xfem_stab_unilat_contact.m                     |   57 +
 cubature/GAUSS.IM.tar                              |  Bin 0 -> 266240 bytes
 cubature/getFemIntGLetGLL.mws                      |  806 +
 doc/BUGS                                           |   14 +
 doc/doxygen/Doxyfile                               | 1472 +
 doc/doxygen/Makefile                               |   10 +
 doc/getfem_project/Makefile                        |   67 +
 doc/getfem_project/cleanup_html_doc.pl             |  130 +
 doc/getfem_project/diagram.fig                     |  109 +
 doc/getfem_project/docstyle.css                    |  221 +
 doc/getfem_project/doxygenlinks.tex                |  123 +
 doc/getfem_project/getfem_project.tex              |  814 +
 doc/getfem_project/getfemelemelem.fig              |   59 +
 doc/getfem_project/getfemelemtrans.fig             |   20 +
 doc/getfem_project/getfemuserelemf.fig             |  109 +
 doc/getfem_project/logo_getfem_small.png           |  Bin 0 -> 27457 bytes
 doc/getfem_project/logogetfem.png                  |  Bin 0 -> 185269 bytes
 doc/getfem_project/logogetfemwhitebg.png           |  Bin 0 -> 144153 bytes
 doc/getfem_project/next.gif                        |  Bin 0 -> 253 bytes
 doc/getfem_project/previous.gif                    |  Bin 0 -> 252 bytes
 doc/getfem_project/underscore.sty                  |  232 +
 doc/getfem_project/up.gif                          |  Bin 0 -> 316 bytes
 doc/getfem_project/updatedoxlinks.py               |  133 +
 doc/gf.txt                                         |   44 +
 doc/gmmuser/Makefile                               |   61 +
 doc/gmmuser/cleanup_html_doc.pl                    |  130 +
 doc/gmmuser/docstyle.css                           |  221 +
 doc/gmmuser/gmmlogo.png                            |  Bin 0 -> 100058 bytes
 doc/gmmuser/gmmlogo_small.png                      |  Bin 0 -> 30535 bytes
 doc/gmmuser/gmmlogowhitebg.png                     |  Bin 0 -> 75944 bytes
 doc/gmmuser/gmmuser.tex                            | 1312 +
 doc/gmmuser/next.gif                               |  Bin 0 -> 253 bytes
 doc/gmmuser/previous.gif                           |  Bin 0 -> 252 bytes
 doc/gmmuser/underscore.sty                         |  232 +
 doc/gmmuser/up.gif                                 |  Bin 0 -> 316 bytes
 doc/kernel/Makefile                                |   30 +
 doc/kernel/getfem_logo.eps                         |15212 ++++++
 doc/kernel/getfemelem.tex                          |  428 +
 doc/kernel/getfemelem_elem.eps                     |  170 +
 doc/kernel/getfemelem_elem.fig                     |   59 +
 doc/kernel/getfemelem_trans.eps                    |  797 +
 doc/kernel/getfemelem_trans.fig                    |   20 +
 doc/kernel/getfemelemfem.tex                       |   16 +
 doc/kernel/getfemelemint.tex                       |   15 +
 doc/kernel/getfemeleminta.tex                      |   38 +
 doc/kernel/getfemlist.tex                          | 1503 +
 doc/kernel/getfemlist_HCT.eps                      |  251 +
 doc/kernel/getfemlist_HCT.fig                      |   69 +
 doc/kernel/getfemlist_RT0.eps                      |  485 +
 doc/kernel/getfemlist_RT0.fig                      |  197 +
 doc/kernel/getfemlist_argyris.eps                  |  240 +
 doc/kernel/getfemlist_argyris.fig                  |   75 +
 doc/kernel/getfemlist_cube_Q1.eps                  |  241 +
 doc/kernel/getfemlist_cube_Q1.fig                  |   61 +
 doc/kernel/getfemlist_cube_Q3.eps                  |  417 +
 doc/kernel/getfemlist_cube_Q3.fig                  |  133 +
 doc/kernel/getfemlist_extrans.eps                  |  759 +
 doc/kernel/getfemlist_extrans.fig                  |   49 +
 doc/kernel/getfemlist_intmethod_quad2.eps          |  136 +
 doc/kernel/getfemlist_intmethod_quad2.fig          |   23 +
 doc/kernel/getfemlist_intmethod_quad3.eps          |  142 +
 doc/kernel/getfemlist_intmethod_quad3.fig          |   25 +
 doc/kernel/getfemlist_intmethod_quad5.eps          |  160 +
 doc/kernel/getfemlist_intmethod_quad5.fig          |   31 +
 doc/kernel/getfemlist_intmethod_tetrahedron1.eps   |  136 +
 doc/kernel/getfemlist_intmethod_tetrahedron1.fig   |   25 +
 doc/kernel/getfemlist_intmethod_tetrahedron2.eps   |  166 +
 doc/kernel/getfemlist_intmethod_tetrahedron2.fig   |   37 +
 doc/kernel/getfemlist_intmethod_tetrahedron3.eps   |  176 +
 doc/kernel/getfemlist_intmethod_tetrahedron3.fig   |   41 +
 doc/kernel/getfemlist_intmethod_tetrahedron5.eps   |  272 +
 doc/kernel/getfemlist_intmethod_tetrahedron5.fig   |   79 +
 doc/kernel/getfemlist_intmethod_triangle1.eps      |  121 +
 doc/kernel/getfemlist_intmethod_triangle1.fig      |   17 +
 doc/kernel/getfemlist_intmethod_triangle2.eps      |  133 +
 doc/kernel/getfemlist_intmethod_triangle2.fig      |   21 +
 doc/kernel/getfemlist_intmethod_triangle2_comp.eps |  206 +
 doc/kernel/getfemlist_intmethod_triangle2_comp.fig |   48 +
 doc/kernel/getfemlist_intmethod_triangle3.eps      |  139 +
 doc/kernel/getfemlist_intmethod_triangle3.fig      |   23 +
 doc/kernel/getfemlist_intmethod_triangle4.eps      |  151 +
 doc/kernel/getfemlist_intmethod_triangle4.fig      |   27 +
 doc/kernel/getfemlist_intmethod_triangle5.eps      |  157 +
 doc/kernel/getfemlist_intmethod_triangle5.fig      |   29 +
 doc/kernel/getfemlist_intmethod_triangle6.eps      |  187 +
 doc/kernel/getfemlist_intmethod_triangle6.fig      |   39 +
 doc/kernel/getfemlist_intmethod_triangle7.eps      |  193 +
 doc/kernel/getfemlist_intmethod_triangle7.fig      |   41 +
 doc/kernel/getfemlist_morley.eps                   |  196 +
 doc/kernel/getfemlist_morley.fig                   |   45 +
 doc/kernel/getfemlist_nedelec.eps                  |  257 +
 doc/kernel/getfemlist_nedelec.fig                  |   63 +
 doc/kernel/getfemlist_prism_P1.eps                 |  183 +
 doc/kernel/getfemlist_prism_P1.fig                 |   41 +
 doc/kernel/getfemlist_prism_P2_P1.eps              |  219 +
 doc/kernel/getfemlist_prism_P2_P1.fig              |   51 +
 doc/kernel/getfemlist_prism_P3.eps                 |  315 +
 doc/kernel/getfemlist_prism_P3.fig                 |   92 +
 doc/kernel/getfemlist_quad8.eps                    |  177 +
 doc/kernel/getfemlist_quad8.fig                    |   33 +
 doc/kernel/getfemlist_quad_Q1.eps                  |  142 +
 doc/kernel/getfemlist_quad_Q1.fig                  |   25 +
 doc/kernel/getfemlist_quad_Q3.eps                  |  214 +
 doc/kernel/getfemlist_quad_Q3.fig                  |   49 +
 doc/kernel/getfemlist_quadc1_composite.eps         |  273 +
 doc/kernel/getfemlist_quadc1_composite.fig         |   95 +
 doc/kernel/getfemlist_reduced_HCT.eps              |  209 +
 doc/kernel/getfemlist_reduced_HCT.fig              |   48 +
 doc/kernel/getfemlist_reduced_quadc1_composite.eps |  259 +
 doc/kernel/getfemlist_reduced_quadc1_composite.fig |   63 +
 doc/kernel/getfemlist_segment_Pk.eps               |  748 +
 doc/kernel/getfemlist_segment_Pk.fig               |   53 +
 doc/kernel/getfemlist_segment_bubble.eps           |  150 +
 doc/kernel/getfemlist_segment_bubble.fig           |   34 +
 doc/kernel/getfemlist_segment_hermite.eps          |  160 +
 doc/kernel/getfemlist_segment_hermite.fig          |   23 +
 doc/kernel/getfemlist_segment_hier.eps             |  450 +
 doc/kernel/getfemlist_segment_hier.fig             |   98 +
 doc/kernel/getfemlist_symbols.eps                  |  381 +
 doc/kernel/getfemlist_symbols.fig                  |  140 +
 doc/kernel/getfemlist_tetrahedron_P1.eps           |  160 +
 doc/kernel/getfemlist_tetrahedron_P1.fig           |   29 +
 doc/kernel/getfemlist_tetrahedron_P1_bubble.eps    |  189 +
 doc/kernel/getfemlist_tetrahedron_P1_bubble.fig    |   46 +
 .../getfemlist_tetrahedron_P1_bubble_face.eps      |  194 +
 .../getfemlist_tetrahedron_P1_bubble_face.fig      |   48 +
 doc/kernel/getfemlist_tetrahedron_P2.eps           |  205 +
 doc/kernel/getfemlist_tetrahedron_P2.fig           |   45 +
 doc/kernel/getfemlist_tetrahedron_P2_bubble.eps    |  225 +
 doc/kernel/getfemlist_tetrahedron_P2_bubble.fig    |   58 +
 doc/kernel/getfemlist_tetrahedron_P3_bubble.eps    |  285 +
 doc/kernel/getfemlist_tetrahedron_P3_bubble.fig    |   78 +
 doc/kernel/getfemlist_tetrahedron_P4.eps           |  263 +
 doc/kernel/getfemlist_tetrahedron_P4.fig           |   67 +
 doc/kernel/getfemlist_tetrahedron_hermite.eps      |  234 +
 doc/kernel/getfemlist_tetrahedron_hermite.fig      |   61 +
 doc/kernel/getfemlist_triangle_P1.eps              |  133 +
 doc/kernel/getfemlist_triangle_P1.fig              |   21 +
 doc/kernel/getfemlist_triangle_P1_bubble.eps       |  162 +
 doc/kernel/getfemlist_triangle_P1_bubble.fig       |   40 +
 doc/kernel/getfemlist_triangle_P1_bubble_face.eps  |  162 +
 doc/kernel/getfemlist_triangle_P1_bubble_face.fig  |   38 +
 doc/kernel/getfemlist_triangle_P1_linbubble.eps    |  505 +
 doc/kernel/getfemlist_triangle_P1_linbubble.fig    |   44 +
 .../getfemlist_triangle_P1_non_conforming.eps      |  133 +
 .../getfemlist_triangle_P1_non_conforming.fig      |   21 +
 doc/kernel/getfemlist_triangle_P1_with_P2_face.eps |  139 +
 doc/kernel/getfemlist_triangle_P1_with_P2_face.fig |   23 +
 doc/kernel/getfemlist_triangle_P1comp.eps          |  185 +
 doc/kernel/getfemlist_triangle_P1comp.fig          |   41 +
 doc/kernel/getfemlist_triangle_P1comp_hier.eps     |  207 +
 doc/kernel/getfemlist_triangle_P1comp_hier.fig     |  104 +
 doc/kernel/getfemlist_triangle_P2.eps              |  151 +
 doc/kernel/getfemlist_triangle_P2.fig              |   27 +
 doc/kernel/getfemlist_triangle_P2_bubble.eps       |  180 +
 doc/kernel/getfemlist_triangle_P2_bubble.fig       |   44 +
 doc/kernel/getfemlist_triangle_P3.eps              |  175 +
 doc/kernel/getfemlist_triangle_P3.fig              |   35 +
 doc/kernel/getfemlist_triangle_P6.eps              |  283 +
 doc/kernel/getfemlist_triangle_P6.fig              |   71 +
 doc/kernel/getfemlist_triangle_hermite.eps         |  174 +
 doc/kernel/getfemlist_triangle_hermite.fig         |   39 +
 doc/kernel/getfemlist_virtual_fem.eps              |  238 +
 doc/kernel/getfemlist_virtual_fem.fig              |   44 +
 doc/kernel/persdf.tex                              |  175 +
 doc/license.tex                                    |   12 +
 doc/sphinx/Makefile.am                             |    8 +-
 doc/sphinx/patch_tools.diff                        |   13 +
 doc/sphinx/source/.static/cuve_3D_streamlines.png  |  Bin 0 -> 169383 bytes
 doc/sphinx/source/.static/favicon.ico              |  Bin 0 -> 4286 bytes
 doc/sphinx/source/.static/gear.png                 |  Bin 0 -> 142274 bytes
 doc/sphinx/source/.static/getfem.css               |  925 +
 doc/sphinx/source/.static/gmmlogo.png              |  Bin 0 -> 100058 bytes
 doc/sphinx/source/.static/hostedbygna.png          |  Bin 0 -> 4696 bytes
 doc/sphinx/source/.static/icon.png                 |  Bin 0 -> 3271 bytes
 doc/sphinx/source/.static/logo_getfem_small.png    |  Bin 0 -> 27457 bytes
 doc/sphinx/source/.static/logogetfem.png           |  Bin 0 -> 185269 bytes
 doc/sphinx/source/.static/strange.mesh_fem         |   98 +
 doc/sphinx/source/.static/strangemesh.png          |  Bin 0 -> 44357 bytes
 doc/sphinx/source/.static/strangernd.png           |  Bin 0 -> 69819 bytes
 .../source/.static/tripodvonmiseswithmesh.png      |  Bin 0 -> 160820 bytes
 doc/sphinx/source/.static/tube.png                 |  Bin 0 -> 359742 bytes
 doc/sphinx/source/.templates/download.html         |  116 +
 doc/sphinx/source/.templates/gmm.html              |  160 +
 doc/sphinx/source/.templates/indexcontent.html     |  166 +
 doc/sphinx/source/.templates/indexsidebar.html     |   22 +
 doc/sphinx/source/.templates/layout.html           |   38 +
 doc/sphinx/source/ACKS.txt                         |   14 +
 doc/sphinx/source/about.rst                        |   33 +
 doc/sphinx/source/biblio.rst                       |   79 +
 doc/sphinx/source/bugs.rst                         |   59 +
 doc/sphinx/source/conf.py                          |  299 +
 doc/sphinx/source/contents.rst                     |   31 +
 doc/sphinx/source/copyright.rst                    |   18 +
 doc/sphinx/source/documenting/fromlatex.rst        |  202 +
 doc/sphinx/source/documenting/index.rst            |   32 +
 doc/sphinx/source/documenting/markup.rst           |  823 +
 doc/sphinx/source/documenting/rest.rst             |  243 +
 doc/sphinx/source/documenting/style.rst            |   70 +
 doc/sphinx/source/glossary.rst                     |   69 +
 doc/sphinx/source/gmm/blas.rst                     |  127 +
 doc/sphinx/source/gmm/blas_interface.rst           |  140 +
 doc/sphinx/source/gmm/catch.rst                    |   26 +
 doc/sphinx/source/gmm/denselu.rst                  |   39 +
 doc/sphinx/source/gmm/denseqr.rst                  |   43 +
 doc/sphinx/source/gmm/export.rst                   |   24 +
 doc/sphinx/source/gmm/first-step.rst               |  116 +
 doc/sphinx/source/gmm/images/gmmlogo.png           |  Bin 0 -> 100058 bytes
 doc/sphinx/source/gmm/index.rst                    |   34 +
 doc/sphinx/source/gmm/inside.rst                   |  227 +
 doc/sphinx/source/gmm/install.rst                  |   50 +
 doc/sphinx/source/gmm/intro.rst                    |   16 +
 doc/sphinx/source/gmm/iter.rst                     |  148 +
 doc/sphinx/source/gmm/matrix.rst                   |  122 +
 doc/sphinx/source/gmm/misc.rst                     |   80 +
 doc/sphinx/source/gmm/noverif.rst                  |   15 +
 doc/sphinx/source/gmm/qd.rst                       |   32 +
 doc/sphinx/source/gmm/sub-matrix.rst               |   73 +
 doc/sphinx/source/gmm/superlu.rst                  |   25 +
 doc/sphinx/source/gmm/triangular.rst               |   22 +
 doc/sphinx/source/license.rst                      |   16 +
 doc/sphinx/source/license.txt                      |   19 +
 doc/sphinx/source/links.rst                        |  102 +
 doc/sphinx/source/lists.rst                        |   18 +
 .../source/matlab/code_samples/demo_laplacian.m    |   55 +
 .../source/matlab/code_samples/demo_step_by_step.m |   46 +
 .../source/matlab/code_samples/demo_tripod.m       |  112 +
 doc/sphinx/source/matlab/examples.rst              |  359 +
 doc/sphinx/source/matlab/images/hierarchy.fig      |   44 +
 .../matlab/images/tripodvonmiseswithmesh.png       |  Bin 0 -> 160820 bytes
 doc/sphinx/source/matlab/index.rst                 |   21 +
 doc/sphinx/source/matlab/install.rst               |   73 +
 doc/sphinx/source/matlab/install_on_mac.rst        |  111 +
 doc/sphinx/source/matlab/intro.rst                 |   17 +
 doc/sphinx/source/matlab/mlabgf.rst                |  150 +
 doc/sphinx/source/matlab/oocmd.rst                 |   98 +
 doc/sphinx/source/matlab/plotcmdref.rst            |  231 +
 doc/sphinx/source/matlab/pre.rst                   |   99 +
 doc/sphinx/source/project/appendixA.rst            |  196 +
 doc/sphinx/source/project/femdesc.rst              |  294 +
 doc/sphinx/source/project/global.rst               |   74 +
 doc/sphinx/source/project/images/diagram.fig       |  111 +
 .../source/project/images/getfemelemelem.fig       |   73 +
 .../source/project/images/getfemtransgeo.fig       |   33 +
 doc/sphinx/source/project/index.rst                |   19 +
 doc/sphinx/source/project/intro.rst                |   96 +
 doc/sphinx/source/project/libdesc.rst              |  720 +
 .../source/python/code_samples/demo_crack.py       |   55 +
 .../python/code_samples/demo_fictitious_domains.py |  110 +
 .../source/python/code_samples/demo_laplacian.py   |  122 +
 .../python/code_samples/demo_step_by_step.py       |   54 +
 .../source/python/code_samples/demo_tripod.py      |   96 +
 .../source/python/code_samples/demo_tripod_alt.py  |  121 +
 doc/sphinx/source/python/code_samples/quad.geo     |   21 +
 doc/sphinx/source/python/code_samples/quad.msh     | 1477 +
 .../source/python/code_samples}/tripod.GiD.msh     |    0
 doc/sphinx/source/python/examples.rst              |  301 +
 doc/sphinx/source/python/howtos.rst                |   39 +
 doc/sphinx/source/python/images/hierarchy.fig      |   46 +
 doc/sphinx/source/python/images/laplacian.png      |  Bin 0 -> 110981 bytes
 doc/sphinx/source/python/images/step_by_step.png   |  Bin 0 -> 89015 bytes
 doc/sphinx/source/python/images/tripod.png         |  Bin 0 -> 811314 bytes
 doc/sphinx/source/python/index.rst                 |   19 +
 doc/sphinx/source/python/install.rst               |  112 +
 doc/sphinx/source/python/intro.rst                 |   17 +
 doc/sphinx/source/python/license.txt               |   11 +
 doc/sphinx/source/python/pre.rst                   |   99 +
 doc/sphinx/source/python/pygf.rst                  |  149 +
 doc/sphinx/source/replaces.txt                     |   97 +
 doc/sphinx/source/scilab/images/hierarchy.fig      |   44 +
 doc/sphinx/source/scilab/index.rst                 |   17 +
 doc/sphinx/source/scilab/install.rst               |   53 +
 doc/sphinx/source/scilab/intro.rst                 |   14 +
 doc/sphinx/source/scilab/plotcmdref.rst            |  225 +
 doc/sphinx/source/scilab/scilabgf.rst              |  154 +
 .../screenshots/code_samples/demo_stokes_2D_tube.m |   63 +
 .../source/screenshots/code_samples/demo_tripod.m  |  112 +
 .../source/screenshots/code_samples/demo_wave2D.m  |  178 +
 doc/sphinx/source/screenshots/helmholtz_source.rst |   15 +
 .../images/cuve_3D_streamlines_small.png           |  Bin 0 -> 82153 bytes
 .../screenshots/images/fissure_3d_de_traviole.png  |  Bin 0 -> 48270 bytes
 doc/sphinx/source/screenshots/images/gear.png      |  Bin 0 -> 54110 bytes
 .../source/screenshots/images/helm_k7_P10_gt6.png  |  Bin 0 -> 90966 bytes
 .../screenshots/images/helm_mesh_k7_P10_gt6.png    |  Bin 0 -> 25826 bytes
 .../images/modestructure_paolo_small.png           |  Bin 0 -> 107007 bytes
 .../screenshots/images/pneu_Q2_vonmises_small.png  |  Bin 0 -> 60565 bytes
 doc/sphinx/source/screenshots/images/shape1.png    |  Bin 0 -> 88079 bytes
 doc/sphinx/source/screenshots/images/shape2.png    |  Bin 0 -> 20605 bytes
 doc/sphinx/source/screenshots/images/shape3.png    |  Bin 0 -> 63857 bytes
 doc/sphinx/source/screenshots/images/shape4.png    |  Bin 0 -> 70623 bytes
 .../screenshots/images/strangemesh_small.png       |  Bin 0 -> 25978 bytes
 .../source/screenshots/images/strangernd_small.png |  Bin 0 -> 32198 bytes
 .../source/screenshots/images/torsion034.png       |  Bin 0 -> 89527 bytes
 .../images/tripodvonmiseswithmesh_small.png        |  Bin 0 -> 70605 bytes
 .../source/screenshots/images/tube_small.png       |  Bin 0 -> 133468 bytes
 doc/sphinx/source/screenshots/images/xfembeam.png  |  Bin 0 -> 275377 bytes
 .../source/screenshots/images/xfembeammesh.png     |  Bin 0 -> 126766 bytes
 doc/sphinx/source/screenshots/shots.rst            |  209 +
 doc/sphinx/source/screenshots/stokes-source.rst    |   15 +
 doc/sphinx/source/screenshots/strange.mesh_fem     |   98 +
 doc/sphinx/source/screenshots/tripod_source.rst    |   15 +
 doc/sphinx/source/userdoc/appendixA.rst            | 1447 +
 doc/sphinx/source/userdoc/appendixB.rst            |  673 +
 doc/sphinx/source/userdoc/asm.rst                  |  205 +
 doc/sphinx/source/userdoc/bfem.rst                 |  343 +
 doc/sphinx/source/userdoc/binteg.rst               |  152 +
 doc/sphinx/source/userdoc/bmesh.rst                |  510 +
 doc/sphinx/source/userdoc/catch.rst                |   25 +
 doc/sphinx/source/userdoc/computeD.rst             |   29 +
 doc/sphinx/source/userdoc/computeL2H1.rst          |   31 +
 doc/sphinx/source/userdoc/convect.rst              |   48 +
 doc/sphinx/source/userdoc/examples.rst             |   29 +
 doc/sphinx/source/userdoc/export.rst               |  280 +
 doc/sphinx/source/userdoc/gasm.rst                 |  209 +
 doc/sphinx/source/userdoc/ifem.rst                 |   22 +
 doc/sphinx/source/userdoc/iinteg.rst               |   52 +
 doc/sphinx/source/userdoc/images/Makefile          |   12 +
 doc/sphinx/source/userdoc/images/getfemlistHCT.fig |   71 +
 doc/sphinx/source/userdoc/images/getfemlistRT0.fig |  207 +
 .../source/userdoc/images/getfemlistargyris.fig    |   77 +
 .../source/userdoc/images/getfemlistcubeQ1.fig     |   63 +
 .../source/userdoc/images/getfemlistcubeQ3.fig     |  135 +
 .../source/userdoc/images/getfemlistincomplete.fig |  111 +
 .../userdoc/images/getfemlistintmethodquad2.fig    |   25 +
 .../userdoc/images/getfemlistintmethodquad3.fig    |   27 +
 .../userdoc/images/getfemlistintmethodquad5.fig    |   33 +
 .../images/getfemlistintmethodtetrahedron1.fig     |   27 +
 .../images/getfemlistintmethodtetrahedron2.fig     |   39 +
 .../images/getfemlistintmethodtetrahedron3.fig     |   43 +
 .../images/getfemlistintmethodtetrahedron5.fig     |   81 +
 .../images/getfemlistintmethodtriangle1.fig        |   19 +
 .../images/getfemlistintmethodtriangle2.fig        |   23 +
 .../images/getfemlistintmethodtriangle2comp.fig    |   50 +
 .../images/getfemlistintmethodtriangle3.fig        |   25 +
 .../images/getfemlistintmethodtriangle4.fig        |   29 +
 .../images/getfemlistintmethodtriangle5.fig        |   31 +
 .../images/getfemlistintmethodtriangle6.fig        |   41 +
 .../images/getfemlistintmethodtriangle7.fig        |   43 +
 .../source/userdoc/images/getfemlistmorley.fig     |   47 +
 .../source/userdoc/images/getfemlistnedelec.fig    |   69 +
 .../source/userdoc/images/getfemlistprismP1.fig    |   41 +
 .../source/userdoc/images/getfemlistprismP2P1.fig  |   53 +
 .../source/userdoc/images/getfemlistprismP3.fig    |   94 +
 .../source/userdoc/images/getfemlistquadQ1.fig     |   27 +
 .../source/userdoc/images/getfemlistquadQ3.fig     |   51 +
 .../userdoc/images/getfemlistquadc1composite.fig   |   97 +
 .../source/userdoc/images/getfemlistreducedHCT.fig |   50 +
 .../images/getfemlistreducedquadc1composite.fig    |   65 +
 .../source/userdoc/images/getfemlistsegmentPk.fig  |   63 +
 .../userdoc/images/getfemlistsegmentbubble.fig     |   36 +
 .../userdoc/images/getfemlistsegmenthermite.fig    |   25 +
 .../userdoc/images/getfemlistsegmenthier.fig       |  100 +
 .../source/userdoc/images/getfemlistsymbols00.fig  |   12 +
 .../source/userdoc/images/getfemlistsymbols01.fig  |   17 +
 .../source/userdoc/images/getfemlistsymbols02.fig  |   17 +
 .../source/userdoc/images/getfemlistsymbols03.fig  |   17 +
 .../source/userdoc/images/getfemlistsymbols04.fig  |   15 +
 .../source/userdoc/images/getfemlistsymbols05.fig  |   16 +
 .../source/userdoc/images/getfemlistsymbols06.fig  |   27 +
 .../source/userdoc/images/getfemlistsymbols07.fig  |   27 +
 .../source/userdoc/images/getfemlistsymbols08.fig  |   27 +
 .../source/userdoc/images/getfemlistsymbols09.fig  |   15 +
 .../source/userdoc/images/getfemlistsymbols10.fig  |   14 +
 .../source/userdoc/images/getfemlistsymbols11.fig  |   16 +
 .../source/userdoc/images/getfemlistsymbols12.fig  |   25 +
 .../source/userdoc/images/getfemlistsymbols13.fig  |   15 +
 .../userdoc/images/getfemlisttetrahedronP1.fig     |   31 +
 .../images/getfemlisttetrahedronP1bubble.fig       |   48 +
 .../images/getfemlisttetrahedronP1bubbleface.fig   |   50 +
 .../userdoc/images/getfemlisttetrahedronP2.fig     |   47 +
 .../images/getfemlisttetrahedronP2bubble.fig       |   60 +
 .../images/getfemlisttetrahedronP3bubble.fig       |   80 +
 .../userdoc/images/getfemlisttetrahedronP4.fig     |   69 +
 .../images/getfemlisttetrahedronhermite.fig        |   63 +
 .../source/userdoc/images/getfemlisttriangleP1.fig |   23 +
 .../userdoc/images/getfemlisttriangleP1bubble.fig  |   42 +
 .../images/getfemlisttriangleP1bubbleface.fig      |   40 +
 .../userdoc/images/getfemlisttriangleP1comp.fig    |   43 +
 .../images/getfemlisttriangleP1comphier.fig        |  106 +
 .../images/getfemlisttriangleP1linbubble.fig       |   46 +
 .../images/getfemlisttriangleP1nonconforming.fig   |   23 +
 .../images/getfemlisttriangleP1withP2face.fig      |   25 +
 .../source/userdoc/images/getfemlisttriangleP2.fig |   29 +
 .../userdoc/images/getfemlisttriangleP2bubble.fig  |   46 +
 .../source/userdoc/images/getfemlisttriangleP3.fig |   37 +
 .../source/userdoc/images/getfemlisttriangleP6.fig |   73 +
 .../userdoc/images/getfemlisttrianglehermite.fig   |   41 +
 .../source/userdoc/images/getfemusercorrection.png |  Bin 0 -> 10640 bytes
 .../source/userdoc/images/getfemuserelem.fig       |   92 +
 .../source/userdoc/images/getfemuserelemf.fig      |  123 +
 .../userdoc/images/getfemuserfrictionlaw.png       |  Bin 0 -> 9423 bytes
 .../userdoc/images/getfemuserfrictionlaw.svg       |  344 +
 .../source/userdoc/images/getfemuserlinearsys.fig  |  105 +
 .../source/userdoc/images/getfemuserlinsysDir.fig  |   97 +
 .../images/getfemusermodeldetectcontact.fig        |   76 +
 .../images/getfemusermodelfalsecontact1.fig        |  296 +
 .../images/getfemusermodelfalsecontact2.fig        |  298 +
 .../userdoc/images/getfemusermodelmasterslave.fig  |   65 +
 .../source/userdoc/images/getfemuserrefine.fig     |  108 +
 doc/sphinx/source/userdoc/index.rst                |   40 +
 doc/sphinx/source/userdoc/install.rst              |  137 +
 doc/sphinx/source/userdoc/interMM.rst              |   46 +
 doc/sphinx/source/userdoc/interNMM.rst             |   57 +
 doc/sphinx/source/userdoc/intro.rst                |   53 +
 doc/sphinx/source/userdoc/linalg.rst               |   45 +
 doc/sphinx/source/userdoc/model.rst                |   61 +
 doc/sphinx/source/userdoc/model_Nitsche.rst        |  220 +
 .../source/userdoc/model_basic_nonlinear.rst       |   39 +
 doc/sphinx/source/userdoc/model_bilaplacian.rst    |   96 +
 doc/sphinx/source/userdoc/model_constraint.rst     |   48 +
 .../source/userdoc/model_contact_friction.rst      |  796 +
 .../model_contact_friction_large_sliding.rst       |  242 +
 doc/sphinx/source/userdoc/model_continuation.rst   |  252 +
 doc/sphinx/source/userdoc/model_dirichlet.rst      |  173 +
 .../source/userdoc/model_elastoplasticity.rst      |  492 +
 doc/sphinx/source/userdoc/model_explicit.rst       |   45 +
 doc/sphinx/source/userdoc/model_fourier_robin.rst  |   41 +
 .../source/userdoc/model_generic_elliptic.rst      |   69 +
 doc/sphinx/source/userdoc/model_helmholtz.rst      |   29 +
 .../source/userdoc/model_linear_elasticity.rst     |  124 +
 doc/sphinx/source/userdoc/model_mass.rst           |   33 +
 .../source/userdoc/model_nonlinear_elasticity.rst  |  345 +
 doc/sphinx/source/userdoc/model_object.rst         |  496 +
 doc/sphinx/source/userdoc/model_poisson.rst        |   86 +
 doc/sphinx/source/userdoc/model_solvers.rst        |   31 +
 doc/sphinx/source/userdoc/model_source_term.rst    |   55 +
 doc/sphinx/source/userdoc/model_time_dispatch.rst  |  286 +
 doc/sphinx/source/userdoc/parallel.rst             |   52 +
 doc/sphinx/source/userdoc/rmesh.rst                |   58 +
 doc/sphinx/source/userdoc/xfem.rst                 |  142 +
 doc/sphinx/source/whatsnew/1.0.rst                 |    7 +
 doc/sphinx/source/whatsnew/1.1.rst                 |    9 +
 doc/sphinx/source/whatsnew/1.2.rst                 |   12 +
 doc/sphinx/source/whatsnew/1.3.rst                 |    8 +
 doc/sphinx/source/whatsnew/1.4.rst                 |   13 +
 doc/sphinx/source/whatsnew/1.5.rst                 |   21 +
 doc/sphinx/source/whatsnew/1.6.rst                 |   39 +
 doc/sphinx/source/whatsnew/1.7.rst                 |   58 +
 doc/sphinx/source/whatsnew/2.0.1.rst               |    8 +
 doc/sphinx/source/whatsnew/2.0.2.rst               |    7 +
 doc/sphinx/source/whatsnew/2.0.rst                 |   46 +
 doc/sphinx/source/whatsnew/3.0.1.rst               |    8 +
 doc/sphinx/source/whatsnew/3.0.rst                 |   33 +
 doc/sphinx/source/whatsnew/3.1.rst                 |    9 +
 doc/sphinx/source/whatsnew/4.0.rst                 |   40 +
 doc/sphinx/source/whatsnew/4.1.1.rst               |   16 +
 doc/sphinx/source/whatsnew/4.1.rst                 |   44 +
 doc/sphinx/source/whatsnew/4.2.rst                 |   40 +
 doc/sphinx/source/whatsnew/index.rst               |   31 +
 doc/userdoc/Makefile                               |  108 +
 doc/userdoc/cleanup_html_doc.pl                    |  130 +
 doc/userdoc/docstyle.css                           |  221 +
 doc/userdoc/doxygenlinks.tex                       |  250 +
 doc/userdoc/getfemlistHCT.fig                      |   69 +
 doc/userdoc/getfemlistRT0.fig                      |  197 +
 doc/userdoc/getfemlistargyris.fig                  |   75 +
 doc/userdoc/getfemlistcubeQ1.fig                   |   61 +
 doc/userdoc/getfemlistcubeQ3.fig                   |  133 +
 doc/userdoc/getfemlistincomplete.fig               |  111 +
 doc/userdoc/getfemlistintmethodquad2.fig           |   23 +
 doc/userdoc/getfemlistintmethodquad3.fig           |   25 +
 doc/userdoc/getfemlistintmethodquad5.fig           |   31 +
 doc/userdoc/getfemlistintmethodtetrahedron1.fig    |   25 +
 doc/userdoc/getfemlistintmethodtetrahedron2.fig    |   37 +
 doc/userdoc/getfemlistintmethodtetrahedron3.fig    |   41 +
 doc/userdoc/getfemlistintmethodtetrahedron5.fig    |   79 +
 doc/userdoc/getfemlistintmethodtriangle1.fig       |   17 +
 doc/userdoc/getfemlistintmethodtriangle2.fig       |   21 +
 doc/userdoc/getfemlistintmethodtriangle2comp.fig   |   48 +
 doc/userdoc/getfemlistintmethodtriangle3.fig       |   23 +
 doc/userdoc/getfemlistintmethodtriangle4.fig       |   27 +
 doc/userdoc/getfemlistintmethodtriangle5.fig       |   29 +
 doc/userdoc/getfemlistintmethodtriangle6.fig       |   39 +
 doc/userdoc/getfemlistintmethodtriangle7.fig       |   41 +
 doc/userdoc/getfemlistmorley.fig                   |   45 +
 doc/userdoc/getfemlistnedelec.fig                  |   63 +
 doc/userdoc/getfemlistprismP1.fig                  |   41 +
 doc/userdoc/getfemlistprismP2P1.fig                |   51 +
 doc/userdoc/getfemlistprismP3.fig                  |   92 +
 doc/userdoc/getfemlistquadQ1.fig                   |   25 +
 doc/userdoc/getfemlistquadQ3.fig                   |   49 +
 doc/userdoc/getfemlistquadc1composite.fig          |   95 +
 doc/userdoc/getfemlistreducedHCT.fig               |   48 +
 doc/userdoc/getfemlistreducedquadc1composite.fig   |   63 +
 doc/userdoc/getfemlistsegmentPk.fig                |   53 +
 doc/userdoc/getfemlistsegmentbubble.fig            |   34 +
 doc/userdoc/getfemlistsegmenthermite.fig           |   23 +
 doc/userdoc/getfemlistsegmenthier.fig              |   98 +
 doc/userdoc/getfemlistsymbols.fig                  |  140 +
 doc/userdoc/getfemlisttetrahedronP1.fig            |   29 +
 doc/userdoc/getfemlisttetrahedronP1bubble.fig      |   46 +
 doc/userdoc/getfemlisttetrahedronP1bubbleface.fig  |   48 +
 doc/userdoc/getfemlisttetrahedronP2.fig            |   45 +
 doc/userdoc/getfemlisttetrahedronP2bubble.fig      |   58 +
 doc/userdoc/getfemlisttetrahedronP3bubble.fig      |   78 +
 doc/userdoc/getfemlisttetrahedronP4.fig            |   67 +
 doc/userdoc/getfemlisttetrahedronhermite.fig       |   61 +
 doc/userdoc/getfemlisttriangleP1.fig               |   21 +
 doc/userdoc/getfemlisttriangleP1bubble.fig         |   40 +
 doc/userdoc/getfemlisttriangleP1bubbleface.fig     |   38 +
 doc/userdoc/getfemlisttriangleP1comp.fig           |   41 +
 doc/userdoc/getfemlisttriangleP1comphier.fig       |  104 +
 doc/userdoc/getfemlisttriangleP1linbubble.fig      |   44 +
 doc/userdoc/getfemlisttriangleP1nonconforming.fig  |   21 +
 doc/userdoc/getfemlisttriangleP1withP2face.fig     |   23 +
 doc/userdoc/getfemlisttriangleP2.fig               |   27 +
 doc/userdoc/getfemlisttriangleP2bubble.fig         |   44 +
 doc/userdoc/getfemlisttriangleP3.fig               |   35 +
 doc/userdoc/getfemlisttriangleP6.fig               |   71 +
 doc/userdoc/getfemlisttrianglehermite.fig          |   39 +
 doc/userdoc/getfemlogo.eps                         |  191 +
 doc/userdoc/getfemuser.css                         |  375 +
 doc/userdoc/getfemuser.tex                         | 4691 ++
 doc/userdoc/getfemuserelem.fig                     |   86 +
 doc/userdoc/getfemuserelemf.fig                    |  109 +
 doc/userdoc/getfemuserlinearsys.fig                |   93 +
 doc/userdoc/getfemuserlinsysDir.fig                |   85 +
 doc/userdoc/getfemuserrefine.fig                   |   86 +
 doc/userdoc/logo_getfem_small.png                  |  Bin 0 -> 27457 bytes
 doc/userdoc/logogetfem.png                         |  Bin 0 -> 185269 bytes
 doc/userdoc/logogetfemwhitebg.png                  |  Bin 0 -> 144153 bytes
 doc/userdoc/next.gif                               |  Bin 0 -> 253 bytes
 doc/userdoc/persdf.tex                             |  176 +
 doc/userdoc/previous.gif                           |  Bin 0 -> 252 bytes
 doc/userdoc/underscore.sty                         |  232 +
 doc/userdoc/up.gif                                 |  Bin 0 -> 316 bytes
 doc/userdoc/updatedoxlinks.py                      |  133 +
 doc/web/doc.php                                    |   92 +
 doc/web/download.php                               |   68 +
 doc/web/footer.inc                                 |    5 +
 doc/web/getfem_faq.php                             |  106 +
 doc/web/getfem_intro.php                           |    8 +
 doc/web/getfempython.php                           |  130 +
 doc/web/gmm_faq.php                                |  109 +
 doc/web/gmm_intro.php                              |    9 +
 doc/web/header.inc                                 |   92 +
 doc/web/index.php                                  |   10 +
 doc/web/links.php                                  |   55 +
 doc/web/news.php                                   |  241 +
 doc/web/roadmap.php                                |   13 +
 doc/web/shots.php                                  |  147 +
 doc/web/support.php                                |   31 +
 doc/web/update_website.sh                          |    5 +
 extract_gmm++                                      |  260 +
 interface/README.txt                               |   95 +
 interface/gnumex                                   |   21 +
 interface/src/Makefile.am                          |   12 +-
 interface/src/getfem_interface.cc                  |   16 +
 interface/src/getfemint.cc                         |   47 +
 interface/src/getfemint.h                          |   21 +
 interface/src/getfemint_cont_struct.h              |   13 +
 interface/src/getfemint_levelset.cc                |    2 +-
 interface/src/getfemint_misc.cc                    |   42 +-
 interface/src/getfemint_multi_contact_frame.h      |   88 +
 interface/src/getfemint_workspace.cc               |   20 +-
 interface/src/getfemint_workspace.h                |   13 +-
 interface/src/gf_asm.cc                            |   28 +-
 interface/src/gf_cont_struct.cc                    |  156 +
 interface/src/gf_cont_struct_get.cc                |  115 +
 interface/src/gf_fem_get.cc                        |   10 +
 interface/src/gf_mdbrick.cc                        |    8 +-
 interface/src/gf_mesh_im.cc                        |   25 +
 interface/src/gf_model_get.cc                      |  236 +-
 interface/src/gf_model_set.cc                      |  478 +-
 interface/src/gf_multi_contact_frame.cc            |   97 +
 interface/src/gf_multi_contact_frame_get.cc        |  149 +
 interface/src/gf_multi_contact_frame_set.cc        |  141 +
 interface/src/gf_poly.cc                           |   84 +
 interface/src/gf_workspace.cc                      |    4 +-
 interface/src/gfi_array.h                          |    5 +
 interface/src/matlab/gf_interpolate_on_grid.m      |   50 +
 interface/src/matlab/gfm_rpc.x                     |   57 +
 interface/src/python/Makefile.am                   |    2 +-
 interface/src/python/getfem_python.c               |    6 +-
 .../src/scilab/demos/data}/disc_2D_degree3.mesh    |    0
 .../src/scilab/demos/data}/disc_P2_h0_3.mesh       |    0
 .../src/scilab/demos/data}/disc_P2_h0_5.mesh       |    0
 .../src/scilab/demos/data}/disc_P2_h10.mesh        |    0
 interface/src/scilab/demos/data/disc_P2_h4.mesh    |  467 +
 .../src/scilab/demos/data}/disc_P2_h6.mesh         |    0
 interface/src/scilab/demos/data/disc_P2_h8.mesh    |  121 +
 .../demos/data}/donut_regulier_32_elements.mesh    |    0
 .../demos/data}/donut_regulier_512_elements.mesh   |    0
 .../demos/data}/donut_regulier_72_elements.mesh    |    0
 .../data}/donut_regulier_8_elements_288ddl.mesh    |    0
 .../sphere_with_quadratic_tetra_16000_elts.mesh    |    0
 .../sphere_with_quadratic_tetra_2000_elts.mesh     |    0
 .../sphere_with_quadratic_tetra_400_elts.mesh      |    0
 .../data}/sphere_with_quadratic_tetra_80_elts.mesh |    0
 .../data}/sphere_with_quadratic_tetra_8_elts.mesh  |    0
 interface/src/scilab/demos/demo_Navier_Stokes.sce  |  165 +
 interface/src/scilab/demos/demo_continuation.sce   |  125 +-
 .../demos/demo_fictitious_domains_laplacian.sce    |  116 +
 .../src/scilab/demos/demo_nonlinear_elasticity.sce |    2 +-
 interface/src/scilab/demos/demo_slices.sce         |   57 +
 interface/src/scilab/help/en_US/getfem_types.xml   |  190 +
 interface/src/scilab/help/en_US/gf_asm.xml         |   32 +
 interface/src/scilab/help/en_US/gf_cont_struct.xml |  127 +
 .../src/scilab/help/en_US/gf_cont_struct_get.xml   |  134 +
 interface/src/scilab/help/en_US/gf_mdbrick.xml     |   10 +
 .../src/scilab/help/en_US/gf_mesher_object.xml     |  136 +
 .../src/scilab/help/en_US/gf_mesher_object_get.xml |   67 +
 interface/src/scilab/help/en_US/gf_model_get.xml   |   16 +
 interface/src/scilab/help/en_US/gf_model_set.xml   |  195 +
 interface/src/scilab/help/en_US/gf_undelete.xml    |   65 +
 interface/src/scilab/help/latex/Makefile           |   99 +
 .../src/scilab/help/latex/cuve3Dstreamlines.png    |  Bin 0 -> 169383 bytes
 .../scilab/help/latex/cuve3Dstreamlinessmall.png   |  Bin 0 -> 169380 bytes
 interface/src/scilab/help/latex/docstyle.css       |  186 +
 interface/src/scilab/help/latex/donut.png          |  Bin 0 -> 212246 bytes
 interface/src/scilab/help/latex/donut_small.png    |  Bin 0 -> 174361 bytes
 interface/src/scilab/help/latex/fempk51.eps        |  366 +
 interface/src/scilab/help/latex/getfemmatlab.lyx   |48778 ++++++++++++++++++++
 interface/src/scilab/help/latex/getfemmatlab.tex   | 4501 ++
 interface/src/scilab/help/latex/hierarchy.eps      |  211 +
 interface/src/scilab/help/latex/hierarchy.fig      |   48 +
 interface/src/scilab/help/latex/license.lyx        |   47 +
 interface/src/scilab/help/latex/license.tex        |   11 +
 .../src/scilab/help/latex/logo_getfem_small.png    |  Bin 0 -> 27457 bytes
 interface/src/scilab/help/latex/logogetfem.png     |  Bin 0 -> 185269 bytes
 .../src/scilab/help/latex/logogetfemwhitebg.png    |  Bin 0 -> 144153 bytes
 interface/src/scilab/help/latex/next.gif           |  Bin 0 -> 253 bytes
 interface/src/scilab/help/latex/previous.gif       |  Bin 0 -> 252 bytes
 interface/src/scilab/help/latex/tripodvonmises.png |  Bin 0 -> 91051 bytes
 .../scilab/help/latex/tripodvonmiseswithmesh.png   |  Bin 0 -> 160820 bytes
 .../help/latex/tripodvonmiseswithmesh_small.png    |  Bin 0 -> 123872 bytes
 interface/src/scilab/help/latex/underscore.sty     |  232 +
 interface/src/scilab/help/latex/up.gif             |  Bin 0 -> 316 bytes
 interface/src/scilab/macros/gf_plot_mesh.sci       |   14 +-
 interface/src/scilab/macros/gf_plot_slice.sci      |    6 +-
 interface/src/scilab/macros/lib                    |  Bin 1152 -> 0 bytes
 interface/src/scilab/macros/names                  |   31 -
 interface/src/scilab/macros/overload/%objid_e.sci  |   15 +
 .../src/scilab/macros/overload/%objid_get.sci      |   15 +
 .../src/scilab/macros/overload/%objid_set.sci      |   15 +
 interface/src/scilab/macros/overload/gf_typeof.sci |   11 +
 .../src/scilab/macros/overload/init_gf_types.sce   |    1 +
 interface/src/scilab/macros/overload/lib           |  Bin 544 -> 0 bytes
 interface/src/scilab/macros/overload/names         |    4 -
 interface/src/scilab/makefile_cleaner.sce          |    2 +
 .../scilab/sci_gateway/c/builder_gateway_c.sce.in  |   82 +
 .../scilab/sci_gateway/c/rebuild_lib_windows.sci   |   43 +
 .../src/scilab/sci_gateway/c/stream_redirect.h     |  100 +
 interface/tests/matlab/Makefile.am                 |    6 +-
 interface/tests/matlab/check_asm.m                 |   22 +-
 interface/tests/matlab/check_interpolated_fem.m    |   64 +
 interface/tests/matlab/check_levelset.m            |   81 +
 .../demo_contact_fictitious_domain_nitsche.m       |  199 +
 interface/tests/matlab/demo_continuation.m         |  123 +
 interface/tests/matlab/demo_dynamic_contact.m      |  466 +
 interface/tests/matlab/demo_elasticity.m           |  121 +
 .../matlab/demo_fictitious_domains_laplacian.m     |    4 +
 interface/tests/matlab/demo_laplacian.m            |   45 +-
 .../tests/matlab/demo_large_sliding_contact.m      |  328 +
 interface/tests/matlab/demo_mortar.m               |    7 +-
 interface/tests/matlab/demo_nonlinear_elasticity.m |   73 +-
 interface/tests/matlab/demo_slices.m               |   57 +
 interface/tests/matlab/demo_static_contact.m       |   76 +
 interface/tests/matlab/demo_step_by_step.m         |   62 +
 .../tests/matlab/demo_topological_optimization.m   |    2 +-
 interface/tests/matlab/demo_tripod.m               |    3 +-
 interface/tests/matlab/demo_wave2D_animate.m       |   30 +
 interface/tests/matlab/plate_Impact.m              |  856 +
 interface/tests/meshes/cuve_linear_2400.GiD.msh    | 3165 ++
 interface/tests/meshes/cuve_quadratic_2400.GiD.msh | 6868 +++
 ...ic_2500.GiD.msh => cuve_quadratic_2500.GiD.msh} |    0
 interface/tests/meshes/donut_regulier.mesh         | 3116 ++
 .../donut_with_quadratic_tetra_1100_elements.msh   | 3366 ++
 interface/tests/meshes/holed_bar.mesh              | 4320 ++
 interface/tests/meshes/ladder.mesh                 | 6111 +++
 interface/tests/meshes/ladder_1500.mesh            | 4631 ++
 interface/tests/meshes/ladder_370.mesh             | 1356 +
 .../tests/meshes/sphere_with_quadratic_tetra.msh   |   69 +
 interface/tests/meshes/tripod.mesh                 | 8403 ++++
 interface/tests/python/Makefile.am                 |   10 +-
 .../tests/python/demo_elastic_ring_contact.py      |  261 +
 .../tests/python/demo_large_sliding_contact.py     |  297 +
 interface/tests/python/demo_parallel_laplacian.py  |  147 +
 interface/tests/python/demo_tripod.py              |    6 +-
 interface/tests/python/quad.geo                    |   25 +
 internal_tools/HCT_reduced_triangle_base.cc        |  301 +
 internal_tools/HCT_triangle_base.cc                |  293 +
 internal_tools/Makefile                            |   16 +
 internal_tools/argyris_base.cc                     |  157 +
 internal_tools/c1_piecep3_quad.cc                  |  278 +
 internal_tools/hermite_tetrahedron_base.cc         |  149 +
 internal_tools/make_donut.C                        |   90 +
 internal_tools/morley_base.cc                      |  159 +
 internal_tools/simplexification_refelt.cc          |  262 +
 m4/acx_getfem.m4                                   |   39 +
 m4/ax_prog_cc_mpi.m4                               |  171 +
 m4/ax_prog_cxx_mpi.m4                              |  180 +
 m4/ax_prog_fc_mpi.m4                               |  162 +
 m4/ltsugar.m4                                      |  123 -
 m4/matlab.m4                                       |  123 +
 m4/matlabver.m4                                    |  133 +
 src/Makefile.am                                    |   25 +-
 src/bgeot_convex_ref.cc                            |  104 +-
 src/bgeot_convex_structure.cc                      |   86 +-
 src/bgeot_ftool.cc                                 |    6 +-
 src/bgeot_geometric_trans.cc                       |  138 +-
 src/bgeot_poly.cc                                  |    4 +
 src/bgeot_poly_composite.cc                        |    8 +-
 src/bgeot_rtree.cc                                 |    3 +-
 src/dal_bit_vector.cc                              |    9 +-
 src/dal_singleton.cc                               |   74 +-
 src/dal_static_stored_objects.cc                   |  656 +-
 src/getfem/bgeot_config.h                          |   11 +-
 src/getfem/bgeot_convex_ref.h                      |   10 +-
 src/getfem/bgeot_convex_structure.h                |    4 +
 src/getfem/bgeot_geometric_trans.h                 |   31 +
 src/getfem/bgeot_tensor.h                          |   35 +-
 src/getfem/dal_bit_vector.h                        |    6 +-
 src/getfem/dal_naming_system.h                     |    8 +-
 src/getfem/dal_singleton.h                         |  209 +-
 src/getfem/dal_static_stored_objects.h             |  503 +-
 src/getfem/getfem_Coulomb_friction.h               |    8 +
 src/getfem/getfem_assembling.h                     |    7 +-
 src/getfem/getfem_assembling_tensors.h             |   25 +-
 src/getfem/getfem_config.h                         |   19 +-
 src/getfem/getfem_contact_and_friction_common.h    |  644 +
 src/getfem/getfem_contact_and_friction_integral.h  |  526 +
 .../getfem_contact_and_friction_large_sliding.h    |  109 +
 src/getfem/getfem_contact_and_friction_nodal.h     |   35 +
 src/getfem/getfem_continuation.h                   |  840 +
 src/getfem/getfem_deformable_mesh.h                |  136 +
 src/getfem/getfem_fem.h                            |   24 +
 src/getfem/getfem_import.h                         |    1 +
 src/getfem/getfem_integration.h                    |    9 +
 src/getfem/getfem_interpolation.h                  |  188 +-
 src/getfem/getfem_level_set_contact.h              |  807 +
 src/getfem/getfem_linearized_plates.h              |    2 +-
 src/getfem/getfem_mat_elem_type.h                  |    3 +-
 src/getfem/getfem_mesh.h                           |   31 +-
 src/getfem/getfem_mesh_fem.h                       |   20 +
 src/getfem/getfem_mesh_region.h                    |   16 +-
 src/getfem/getfem_mesher.h                         |    2 +-
 src/getfem/getfem_models.h                         |  584 +-
 src/getfem/getfem_nonlinear_elasticity.h           |   42 +-
 src/getfem/getfem_omp.h                            |  330 +
 src/getfem/getfem_plasticity.h                     |  890 +-
 src/getfem/getfem_projected_fem.h                  |    9 +
 src/getfem/getfem_spider_fem.h                     |    4 +-
 src/getfem_assembling_tensors.cc                   |   26 +-
 src/getfem_boost/README                            |    3 +
 src/getfem_contact_and_friction_common.cc          | 1264 +
 src/getfem_contact_and_friction_integral.cc        | 2783 +-
 src/getfem_contact_and_friction_large_sliding.cc   | 2216 +
 src/getfem_contact_and_friction_nodal.cc           |   60 +-
 src/getfem_deformable_mesh.cc                      |   42 +
 src/getfem_enumeration_dof_para.cc                 |  498 +
 src/getfem_fem.cc                                  |    2 +-
 src/getfem_fem_composite.cc                        |    2 +-
 src/getfem_fourth_order.cc                         |    9 +-
 src/getfem_import.cc                               |  165 +-
 src/getfem_integration.cc                          |   23 +-
 src/getfem_interpolation.cc                        |   49 +-
 src/getfem_level_set_contact.cc                    |  818 +
 src/getfem_mat_elem.cc                             |  752 +-
 src/getfem_mat_elem_type.cc                        |   88 +-
 src/getfem_mesh.cc                                 |   14 +-
 src/getfem_mesh_im_level_set.cc                    |   48 +-
 src/getfem_mesh_region.cc                          |   49 +-
 src/getfem_mesher.cc                               |    8 +-
 src/getfem_model_solvers.cc                        |   85 +-
 src/getfem_models.cc                               | 3138 +-
 src/getfem_nonlinear_elasticity.cc                 |  233 +-
 src/getfem_omp.cc                                  |  131 +
 src/getfem_plasticity.cc                           | 1021 +-
 src/getfem_projected_fem.cc                        |  180 +
 src/gmm/gmm_MUMPS_interface.h                      |   45 +-
 src/gmm/gmm_blas.h                                 |   14 +-
 src/gmm/gmm_def.h                                  |    2 +-
 src/gmm/gmm_dense_lu.h                             |    6 +-
 src/gmm/gmm_except.h                               |   16 +-
 src/gmm/gmm_inoutput.h                             |   31 +-
 src/gmm/gmm_lapack_interface.h                     |    4 +-
 src/gmm/gmm_matrix.h                               |   15 +-
 src/gmm/gmm_opt.h                                  |    8 +-
 src/gmm/gmm_precond_diagonal.h                     |    2 +-
 src/gmm/gmm_solver_bfgs.h                          |   10 +-
 src/gmm/gmm_std.h                                  |  339 +-
 src/gmm/gmm_sub_index.h                            |    4 +
 src/gmm/gmm_vector.h                               |    4 +-
 superlu/LOCAL_PATCHES.txt                          |   82 +
 superlu/dgstrsL.c                                  |  233 +
 superlu/mkBLAS.py                                  |   24 +
 superlu/xerbla.c                                   |   43 +
 tests-2.0/Makefile.am                              |   58 +-
 tests-2.0/helmholtz.param                          |   48 +
 tests-2.0/nonlinear_elastostatic.cc                |    2 +-
 tests-2.0/nonlinear_elastostatic.param             |    2 +-
 tests-2.0/plasticity.param                         |   87 +
 tests-2.0/test_assembly.cc                         |    4 +-
 tests-2.0/test_grad.cc                             |  169 +
 tests-2.0/test_mat_elem.param                      |   36 +
 tests-2.0/test_superlu.cc                          |  116 +
 tests/Makefile.am                                  |   51 +-
 tests/dynamic_friction.param2                      |   94 +
 tests/dynamic_friction_anim.net                    |  828 +
 tests/elastostatic.param                           |    2 +-
 tests/gmm_torture02_baseop.cc                      |   63 +
 tests/helmholtz.param                              |   48 +
 tests/laplacian_conv_pk.pl                         |  437 +
 tests/make_gmm_test.pl                             |    4 +-
 .../{disc_P2_h0_3.mesh => disc_P2_h0_3.mesh~HEAD}  |    0
 ...isc_P2_h0_3.mesh => disc_P2_h0_3.mesh~upstream} |    0
 .../{disc_P2_h0_5.mesh => disc_P2_h0_5.mesh~HEAD}  |    0
 ...isc_P2_h0_5.mesh => disc_P2_h0_5.mesh~upstream} |    0
 .../{disc_P2_h10.mesh => disc_P2_h10.mesh~HEAD}    |    0
 ...{disc_P2_h10.mesh => disc_P2_h10.mesh~upstream} |    0
 .../{disc_P2_h6.mesh => disc_P2_h6.mesh~HEAD}      |    0
 .../{disc_P2_h6.mesh => disc_P2_h6.mesh~upstream}  |    0
 tests/meshes/multi_body.mesh                       | 5885 +++
 tests/meshes/punch2D_1.mesh                        |  606 +
 tests/meshes/punch2D_2.mesh                        | 2333 +
 tests/nonlinear_elastostatic.param                 |    2 +-
 tests/test_assembly.cc                             |    4 +-
 tests/test_continuation.cc                         |  126 +
 tests/test_continuation.param                      |   34 +
 tests/test_gmm_lapack.cc                           |  127 +
 tests/test_grad.cc                                 |  166 +
 tests/test_large_sliding_contact.cc                |    8 +
 tests/test_mat_elem.param                          |   36 +
 tests/test_mesh.cc                                 |  105 +
 tests/test_superlu.cc                              |  114 +
 tests/toto.net                                     |  771 +
 932 files changed, 296751 insertions(+), 4292 deletions(-)

diff --cc bin/extract_doc
index c8b03d6,4886040..1c07ea0
--- a/bin/extract_doc
+++ b/bin/extract_doc
@@@ -1,7 -1,7 +1,11 @@@
  #!/usr/bin/env python
  # -*- python -*-
  #
++<<<<<<< HEAD
 +# Copyright (C) 2004-2012 Yves Renard, Julien Pommier.
++=======
+ # Copyright (C) 2004-2013 Yves Renard, Julien Pommier.
++>>>>>>> upstream
  #                                                       
  # This file is a part of GETFEM++                                         
  #                                                                         
@@@ -301,6 -301,7 +305,10 @@@ def FilterDoc(d, langage, objects, comm
  
      # Authorized abbreviations
      d = string.replace(d, '@tcs',    'cont_struct')
++<<<<<<< HEAD
++=======
+     d = string.replace(d, '@tmcf',   'multi_contact_frame')
++>>>>>>> upstream
      d = string.replace(d, '@tmf',    'mesh_fem')
      d = string.replace(d, '@tbrick', 'mdbrick')
      d = string.replace(d, '@tstate', 'mdstate')
@@@ -872,33 -873,34 +880,64 @@@ elif (option == 'matlab-doc')
    print 'The expected type of each function argument is indicated in this '
    print 'reference. Here is a list of these types:'
    print ''
++<<<<<<< HEAD
 +  print '=================  =================================================='
 +  print '`int`              integer value'
 +  print '`hobj`             a handle for any getfem++ object'
 +  print '`scalar`           scalar value'
 +  print '`string`           string'
 +  print '`ivec`             vector of integer values'
 +  print '`vec`              vector'
 +  print '`imat`             matrix of integer values'
 +  print '`mat`              matrix'
 +  print '`spmat`            sparse matrix (both matlab native sparse'
 +  print '                   matrices, and getfem sparse matrices)'
 +  print '`precond`          getfem preconditioner object'
 +  print '`mesh mesh`        object descriptor (or gfMesh object)'
 +  print '`mesh_fem`         mesh fem object descriptor (or gfMeshFem object)'
 +  print '`mesh_im`          mesh im object descriptor( or gfMeshIm object)'
 +  print '`mesh_slice`       mesh slice object descriptor (or gfSlice object)'
 +  print '`cvstruct`         convex structure descriptor (or gfCvStruct object)'
 +  print '`geotrans`         geometric transformation descriptor (or '
 +  print '                   gfGeoTrans object)'
 +  print '`fem`              fem descriptor (or gfFem object)'
 +  print '`eltm`             elementary matrix descriptor (or gfEltm object)'
 +  print '`integ`            integration method descriptor (or gfInteg object)'
 +  print '`model`            model descriptor (or gfModel object)'
 +  print '`global_function`  global function descriptor'
 +  print '`mesher_object`    mesher object descriptor'
 +  print '`cont_struct`      continuation-structure descriptor'
 +  print '=================  =================================================='
++=======
+   print '=====================  =================================================='
+   print '`int`                  integer value'
+   print '`hobj`                 a handle for any getfem++ object'
+   print '`scalar`               scalar value'
+   print '`string`               string'
+   print '`ivec`                 vector of integer values'
+   print '`vec`                  vector'
+   print '`imat`                 matrix of integer values'
+   print '`mat`                  matrix'
+   print '`spmat`                sparse matrix (both matlab native sparse'
+   print '                       matrices, and getfem sparse matrices)'
+   print '`precond`              getfem preconditioner object'
+   print '`mesh mesh`            object descriptor (or gfMesh object)'
+   print '`mesh_fem`             mesh fem object descriptor (or gfMeshFem object)'
+   print '`mesh_im`              mesh im object descriptor( or gfMeshIm object)'
+   print '`mesh_slice`           mesh slice object descriptor (or gfSlice object)'
+   print '`cvstruct`             convex structure descriptor (or gfCvStruct object)'
+   print '`geotrans`             geometric transformation descriptor (or '
+   print '                       gfGeoTrans object)'
+   print '`fem`                  fem descriptor (or gfFem object)'
+   print '`eltm`                 elementary matrix descriptor (or gfEltm object)'
+   print '`integ`                integration method descriptor (or gfInteg object)'
+   print '`model`                model descriptor (or gfModel object)'
+   print '`global_function`      global function descriptor'
+   print '`mesher_object`        mesher object descriptor'
+   print '`cont_struct`          continuation-structure descriptor'
+   print '`multi_contact_frame`  multi-contact descriptor'
+   print '=====================  =================================================='
++>>>>>>> upstream
    print ''  
    print 'Arguments listed between square brackets are optional. Lists between braces indicate that the argument must match one of the elements of the list. For example::'
    print ''
@@@ -1194,6 -1196,14 +1233,17 @@@ elif (option == 'scilab-com')
    mfile.write('      </varlistentry>\n\n')
    mfile.write('    </variablelist>\n\n')
  
++<<<<<<< HEAD
++=======
+   mfile.write('      <varlistentry>\n')
+   mfile.write('        <term>multi_contact_frame</term>\n')
+   mfile.write('        <listitem>\n')
+   mfile.write('          <para>multi-contact descriptor</para>\n')
+   mfile.write('        </listitem>\n')
+   mfile.write('      </varlistentry>\n\n')
+   mfile.write('    </variablelist>\n\n')
+ 
++>>>>>>> upstream
    mfile.write('    <para>Arguments listed between square brackets are optional. Lists between braces indicate</para>\n')
    mfile.write('    <para>that the argument must match one of the elements of the list. For example:</para>\n\n')
  
@@@ -1217,25 -1227,25 +1267,47 @@@
        if (os.path.exists(src_dir) and os.path.isfile(src_dir)):
  
          mfile = open('gf_'+o+ext+'.xml', 'w')
++<<<<<<< HEAD
+         
+         mfile.write('<?xml version="1.0" encoding="UTF-8"?>\n')
+         mfile.write('<refentry version="5.0-subset Scilab" xml:id="gf_' + o + ext + '" xml:lang="en"\n')
+         mfile.write('          xmlns="http://docbook.org/ns/docbook"\n')
+         mfile.write('          xmlns:xlink="http://www.w3.org/1999/xlink"\n')
+         mfile.write('          xmlns:xi="http://www.w3.org/2001/XInclude"\n')
+         mfile.write('          xmlns:svg="http://www.w3.org/2000/svg"\n')
+         mfile.write('          xmlns:mml="http://www.w3.org/1998/Math/MathML"\n')
+         mfile.write('          xmlns:html="http://www.w3.org/1999/xhtml"\n')
+         mfile.write('          xmlns:db="http://docbook.org/ns/docbook">\n')
+ 
+         [gdoc, args] = ExtractGlobalDoc(src_dir);
+         gdoc = FilterDoc(gdoc, langage, objects, commands)
+ 
+         mfile.write('  <refnamediv>\n')
+         mfile.write('    <refname>gf_' + o + ext + '</refname>\n')
+         mfile.write('    <refpurpose>' + gdoc + '</refpurpose>\n')
+         mfile.write('  </refnamediv>\n\n')
+         
++=======
 +        
 +        mfile.write('<?xml version="1.0" encoding="UTF-8"?>\n')
 +        mfile.write('<refentry version="5.0-subset Scilab" xml:id="gf_' + o + ext + '" xml:lang="en"\n')
 +        mfile.write('          xmlns="http://docbook.org/ns/docbook"\n')
 +        mfile.write('          xmlns:xlink="http://www.w3.org/1999/xlink"\n')
 +        mfile.write('          xmlns:xi="http://www.w3.org/2001/XInclude"\n')
 +        mfile.write('          xmlns:svg="http://www.w3.org/2000/svg"\n')
 +        mfile.write('          xmlns:mml="http://www.w3.org/1998/Math/MathML"\n')
 +        mfile.write('          xmlns:html="http://www.w3.org/1999/xhtml"\n')
 +        mfile.write('          xmlns:db="http://docbook.org/ns/docbook">\n')
 +
 +        [gdoc, args] = ExtractGlobalDoc(src_dir);
 +        gdoc = FilterDoc(gdoc, langage, objects, commands)
 +
 +        mfile.write('  <refnamediv>\n')
 +        mfile.write('    <refname>gf_' + o + ext + '</refname>\n')
 +        mfile.write('    <refpurpose>' + gdoc + '</refpurpose>\n')
 +        mfile.write('  </refnamediv>\n\n')
 +        
++>>>>>>> upstream
          mfile.write('  <refsynopsisdiv>\n')
          mfile.write('    <title>Calling Sequence</title>\n\n')
  
@@@ -1361,33 -1371,34 +1433,64 @@@ elif (option == 'scilab-doc-rst')
    print 'The expected type of each function argument is indicated in this '
    print 'reference. Here is a list of these types:'
    print ''
++<<<<<<< HEAD
 +  print '=================  =================================================='
 +  print '`int`              integer value'
 +  print '`hobj`             a handle for any getfem++ object'
 +  print '`scalar`           scalar value'
 +  print '`string`           string'
 +  print '`ivec`             vector of integer values'
 +  print '`vec`              vector'
 +  print '`imat`             matrix of integer values'
 +  print '`mat`              matrix'
 +  print '`spmat`            sparse matrix (both matlab native sparse'
 +  print '                   matrices, and getfem sparse matrices)'
 +  print '`precond`          getfem preconditioner object'
 +  print '`mesh mesh`        object descriptor (or gfMesh object)'
 +  print '`mesh_fem`         mesh fem object descriptor (or gfMeshFem object)'
 +  print '`mesh_im`          mesh im object descriptor( or gfMeshIm object)'
 +  print '`mesh_slice`       mesh slice object descriptor (or gfSlice object)'
 +  print '`cvstruct`         convex structure descriptor (or gfCvStruct object)'
 +  print '`geotrans`         geometric transformation descriptor (or '
 +  print '                   gfGeoTrans object)'
 +  print '`fem`              fem descriptor (or gfFem object)'
 +  print '`eltm`             elementary matrix descriptor (or gfEltm object)'
 +  print '`integ`            integration method descriptor (or gfInteg object)'
 +  print '`model`            model descriptor (or gfModel object)'
 +  print '`global_function`  global function descriptor'
 +  print '`mesher_object`    mesher object descriptor'
 +  print '`cont_struct`      continuation-structure descriptor'
 +  print '=================  =================================================='
++=======
+   print '=====================  =================================================='
+   print '`int`                  integer value'
+   print '`hobj`                 a handle for any getfem++ object'
+   print '`scalar`               scalar value'
+   print '`string`               string'
+   print '`ivec`                 vector of integer values'
+   print '`vec`                  vector'
+   print '`imat`                 matrix of integer values'
+   print '`mat`                  matrix'
+   print '`spmat`                sparse matrix (both matlab native sparse'
+   print '                       matrices, and getfem sparse matrices)'
+   print '`precond`              getfem preconditioner object'
+   print '`mesh mesh`            object descriptor (or gfMesh object)'
+   print '`mesh_fem`             mesh fem object descriptor (or gfMeshFem object)'
+   print '`mesh_im`              mesh im object descriptor( or gfMeshIm object)'
+   print '`mesh_slice`           mesh slice object descriptor (or gfSlice object)'
+   print '`cvstruct`             convex structure descriptor (or gfCvStruct object)'
+   print '`geotrans`             geometric transformation descriptor (or '
+   print '                       gfGeoTrans object)'
+   print '`fem`                  fem descriptor (or gfFem object)'
+   print '`eltm`                 elementary matrix descriptor (or gfEltm object)'
+   print '`integ`                integration method descriptor (or gfInteg object)'
+   print '`model`                model descriptor (or gfModel object)'
+   print '`global_function`      global function descriptor'
+   print '`mesher_object`        mesher object descriptor'
+   print '`cont_struct`          continuation-structure descriptor'
+   print '`multi_contact_frame`  multi-contact descriptor'
+   print '=====================  =================================================='
++>>>>>>> upstream
    print ''  
    print 'Arguments listed between square brackets are optional. Lists between braces indicate that the argument must match one of the elements of the list. For example::'
    print ''
diff --cc configure.ac
index 0000000,232666f..f02c135
mode 000000,100644..100644
--- a/configure.ac
+++ b/configure.ac
@@@ -1,0 -1,1167 +1,1272 @@@
+ dnl Process this file with autoconf to produce a configure script.
+ dnl ------------------------------------------------------------------------
+ dnl initialisation
+ dnl ------------------------------------------------------------------------
+ 
+ dnl ./configure: sh internal 2K buffer overflow on HP-UX 9.xx
+ dnl thus, updating cache ./config.cache avoided.
+ define([AC_CACHE_LOAD], )dnl
+ define([AC_CACHE_SAVE], )dnl
+ 
+ AC_INIT(getfem, 4.2)
+ MAJOR_VERSION="4"
+ MINOR_VERSION="2"
+ PATCH_VERSION="0"
+ 
+ AC_CONFIG_SRCDIR([install-sh])
+ AC_CONFIG_MACRO_DIR([m4])
+ AC_CONFIG_HEADER(config.h)
+ AX_PREFIX_CONFIG_H(src/getfem/getfem_arch_config.h,GETFEM) 
+ AC_PREREQ(2.61)
+ AC_ARG_PROGRAM
+ 
+ dnl PACKAGE="getfem"
+ dnl dnl VERSION=$MAJOR_VERSION.$MINOR_VERSION-`date +%Y%m%d`
+ dnl VERSION=$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION
+ dnl dnl VERSION=$MAJOR_VERSION.$MINOR_VERSION
+ dnl AC_DEFINE_UNQUOTED([MAJOR_VERSION],$MAJOR_VERSION,[getfem major version number])
+ dnl AC_DEFINE_UNQUOTED([MINOR_VERSION],$MINOR_VERSION,[getfem minor version number])
+ dnl AC_DEFINE_UNQUOTED([PATCH_VERSION],$PATCH_VERSION,[getfem patch number (sub minor version)])
+ dnl echo "configuring $PACKAGE $VERSION (patch level $PATCH_VERSION)..."
+ 
+ 
+ dnl ------------------------------------------------------------------------
+ dnl   init automake
+ dnl ------------------------------------------------------------------------
+ 
+ dnl AM_INIT_AUTOMAKE($PACKAGE,$VERSION)
+ AM_INIT_AUTOMAKE(1.10.1) 
+ 
+ dnl --------------------------
+ dnl set the optimization level
+ dnl --------------------------
+ 
+ AC_ARG_WITH(optimization,
+ 	    AC_HELP_STRING([--with-optimization=FLAG],[Set the optimization level (-O3 by default)]),
+ 	    [with_optimization=$withval],
+ 	    [with_optimization='-O3']
+ 	    )
+ 
+ 
+ dnl ---------------------------PARA LEVEL--------------------------
+ paralevel=0
+ AC_ARG_ENABLE(paralevel,
+    [AS_HELP_STRING([--enable-paralevel[=level]],[enable the parallel version fo Getfem (use MPI and METIS)])],
+    [ case $enableval in
+         yes | "") paralevel=2;;
+         no) ;;
+         *) paralevel=$enableval ;;
+      esac
+ ])
+ 
+ if test $paralevel -ge 1; then
+   CPPFLAGS="$CPPFLAGS -DGETFEM_PARA_LEVEL=$paralevel"
+ fi;
+ dnl ---------------------------END OF PARA LEVEL--------------------------
+ 
+ 
+ 
+ dnl -----------------------------------------------
+ dnl test du c++
+ dnl -----------------------------------------------
+ 
+ USER_CXXFLAGS="$CXXFLAGS"
+ USER_CFLAGS="$CFLAGS"
+ AX_PROG_CXX_MPI([test $paralevel -ge 1],[usempi=yes],[usempi=no])
+ AX_PROG_CC_MPI([test "x$usempi" = "xyes"],,[usempi=no])
+ AX_PROG_FC_MPI([test "x$usempi" = "xyes"],[CPPFLAGS="$CPPFLAGS -DGMM_USES_MPI"],[usempi=no])
+ 
+ AC_PROG_CXXCPP
+ CXXFLAGS="${USER_CXXFLAGS}"
+ CFLAGS="${USER_CFLAGS}"
+ SUPLDFLAGS=""
+ AC_FC_LIBRARY_LDFLAGS
+ 
+ AC_LANG([C++])
+ 
+ if test "x$prefix" = "xNONE"; then
+   GFPREFIX=/usr/local;
+ else
+   GFPREFIX="$prefix";
+ fi;
+ 
+ dnl AC_CXX_FULL_SPECIALIZATION_SYNTAX (c)Luc Maisonobe v 1.1.1.1 (2001/07/26)     0.5.41 
+ dnl with some modification to test partial specialization
+ AC_CACHE_CHECK(whether the compiler recognizes the partial specialization syntax,
+ ac_cv_cxx_partial_specialization_syntax,
+ [AC_DIAGNOSE([obsolete],[Instead of using `AC_LANG', `AC_LANG_SAVE', and `AC_LANG_RESTORE',
+ you should use `AC_LANG_PUSH' and `AC_LANG_POP'.])dnl
+ AC_LANG_SAVE
+  AC_LANG([C++])
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ template<class T> class A        { public : int f () const { return 1; } };
+ template<class T> class A<T*>    { public : int f () const { return 0; } };]], [[
+ A<float*> a; return a.f();]])],[ac_cv_cxx_partial_specialization_syntax=yes],[ac_cv_cxx_partial_specialization_syntax=no])
+  AC_LANG_POP([])
+ ])
+ if test "$ac_cv_cxx_partial_specialization_syntax" != yes; then
+   echo "Your compiler ($CXX) does not support partial template specialization, trash it"
+   exit 1;
+ fi
+ 
+ AC_CANONICAL_HOST
+ 
+ echo "you are compiling GetFEM++ on a $host"
+ 
+ case $CXX in
+  cxx)
+ 	echo "Using Compaq cxx compiler"
+ 	echo "WARNING : Control that you have at least Compaq C++ V6.3"
+  	here=`pwd`
+  	cd $srcdir
+ dnl     il faut utiliser -tweak au lieu des repositories ...
+ 	CXXFLAGS="$CXXFLAGS -tweak -std strict_ansi -fast -Wl,-S -nopure_cname"
+ dnl 	CXXFLAGS="$CXXFLAGS -ptr `pwd`/cxx_repository -std strict_ansi $with_optimization"
+ 	CFLAGS="$CFLAGS -fast -Wl,-S"
+  	cd $here
+ 	;;
+  CC)
+ 	case $host in
+ 	*irix*)
+ 		echo "Using MIPSPRO CC on IRIX  (LD is set to CC)"
+ 		LD=CC   dnl sinon getfem_matlab a des probl�mes (unresolved symbol __record_needed_destruction)
+ dnl 		CXXFLAGS="$CXXFLAGS -LANG:std $with_optimization -OPT:Olimit=0:roundoff=3:div_split=ON:alias=typed -TARG:platform=ip25"
+  		CXXFLAGS="$CXXFLAGS -LANG:std $with_optimization "
+ dnl             CXXFLAGS="$CXXFLAGS -LANG:std $with_optimization -ansiW "
+ 		SUPLDFLAGS="-lCio"
+ 		;;
+ 	*sun*)
+ 		echo "Using SUN C++ WorkShop Compiler"
+ 		CXXFLAGS="$CXXFLAGS +w2 $with_optimization -library=stlport4"
+ 		;;
+ 	esac
+ 	;;
+  aCC)
+ 	echo "Using HP ANSI C++ Compiler aCC"
+ 	CXXFLAGS="$CXXFLAGS -AA -fast"	
+ 	;;
+ 	
+  *g++* | c++)
+ 	GCCVER=`$CXX --version | head -1 | cut -d ' ' -f3`
+ 	echo "Using the GNU g++ compiler $GCCVER"
+ 	AC_CHECK_CXX_FLAG([$with_optimization],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wall -W],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-fmessage-length=0],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-ftemplate-depth-40],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-pedantic],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wshadow],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wno-unknown-pragmas],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wpointer-arith],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wcast-qual],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wwrite-strings],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wconversion],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wredundant-decls],CXXFLAGS)
+ 	dnl -Wno-long-double fixes a warning on Darwin
+ 	dnl AC_CHECK_CXX_FLAG([-Wno-long-double],CXXFLAGS)
+ 	AC_CHECK_CXX_FLAG([-Wno-long-long],CXXFLAGS)
+ 	dnl -rdynamic used for backtraces
+ 	AC_CHECK_CXX_FLAG([-rdynamic],SUPLDFLAGS)
+ 
+ dnl 	CXXFLAGS="$CXXFLAGS -fmessage-length=0 -ftemplate-depth-40 -pedantic $with_optimization -Wall -W $WSHADOW -Wpointer-arith -Wcast-qual -Wwrite-strings -Wconversion -Wredundant-decls -Wno-long-double"
+ dnl	SUPLDFLAGS="-rdynamic" # -rdynamic for backtraces
+         CFLAGS="$CFLAGS $with_optimization"
+ 	;;
+  icc | icpc)
+ 	echo "Using INTEL icc"
+ dnl -tpp6 is for pentiumII and more
+ dnl -Xc is for ansi conformance
+ 	CXXFLAGS="$CXXFLAGS $with_optimization -Xc -ansi"
+         CFLAGS="$CFLAGS $with_optimization -Xc -ansi"
+ 	;;
+  *)
+ 	echo "Using a unknown compiler"
+  	CXXFLAGS="$CXXFLAGS $with_optimization"
+         CFLAGS="$CFLAGS $with_optimization"
+ 	;;
+ esac
+ 
+ AC_SUBST(SUPLDFLAGS)
+ 
+ dnl ------------------------------------------------------------------------
+ dnl   init libtools for shared libraries
+ dnl ------------------------------------------------------------------------
+ 
+ dnl option pic-only is not working: a libtool bug ...
+ LT_INIT([pic-only disable-shared])
+ AC_SUBST([LIBTOOL_DEPS])
+ 
+ dnl -------------------------------BLAS----------------------------------
+ 
+ dnl why I hate autoconf: if the code below is put into a separate file,
+ dnl the generated ./configure will stop if no Fortran compiler is found. always. even
+ dnl if no AC_FC_FUNC is executed.
+ acx_blas_ok=no
+ 
+ AC_ARG_WITH(blas,
+         [AS_HELP_STRING([--with-blas=<lib>],[use BLAS library <lib>])])
+ case $with_blas in
+         yes | "") ;;
+         no) acx_blas_ok=disable ;;
+         -* | */* | *.a | *.so | *.so.* | *.o| builtin) BLAS_LIBS="$with_blas" ;;
+         *) BLAS_LIBS="-l$with_blas" ;;
+ esac
+ 
+ # Get fortran linker names of BLAS functions to check for.
+ if test x"$FC" = "x"; then
+   echo "No fortran compiler found, assuming c-name for SGEMM is 'sgemm_'"
+   sgemm=sgemm_
+   dgemm=dgemm_
+ else
+   AC_FC_FUNC(sgemm)
+   AC_FC_FUNC(dgemm)
+ fi
+ acx_blas_save_LIBS="$LIBS"
+ LIBS="$LIBS $FLIBS"
+ echo "BLAS_LIBS=$BLAS_LIBS"
+ # First, check BLAS_LIBS environment variable
+ if test "x$BLAS_LIBS" = xbuiltin; then
+   echo "Using builtin blas lib";
+   BLAS_LIBS=""
+ else
+ 
+ if test $acx_blas_ok = no; then
+   if test "x$BLAS_LIBS" != x; then
+         save_LIBS="$LIBS"; LIBS="$BLAS_LIBS $LIBS"
+         AC_MSG_CHECKING([for $sgemm in $BLAS_LIBS])
+         AC_TRY_LINK_FUNC($sgemm, [acx_blas_ok=yes], [BLAS_LIBS=""])
+         AC_MSG_RESULT($acx_blas_ok)
+         LIBS="$save_LIBS"
+   fi
+ fi
+ 
+ # BLAS linked to by default?  (happens on some supercomputers)
+ if test $acx_blas_ok = no; then
+         save_LIBS="$LIBS"; LIBS="$LIBS"
+         AC_CHECK_FUNC($sgemm, [acx_blas_ok=yes])
+         LIBS="$save_LIBS"
+ fi
+ 
+ # BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(atlas, ATL_xerbla,
+                 [AC_CHECK_LIB(f77blas, $sgemm,
+                 [AC_CHECK_LIB(cblas, cblas_dgemm,
+                         [acx_blas_ok=yes
+                          BLAS_LIBS="-lf77blas -latlas $FCLIBS"],
+                         [], [-lf77blas -latlas])],
+                         [], [-latlas])])
+ fi
+ 
+ # BLAS in PhiPACK libraries? (requires generic BLAS lib, too)
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(blas, $sgemm,
+                 [AC_CHECK_LIB(dgemm, $dgemm,
+                 [AC_CHECK_LIB(sgemm, $sgemm,
+                         [acx_blas_ok=yes; BLAS_LIBS="-lsgemm -ldgemm -lblas"],
+                         [], [-lblas])],
+                         [], [-lblas])])
+ fi
+ 
+ # BLAS in Alpha CXML library?
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(cxml, $sgemm, [acx_blas_ok=yes;BLAS_LIBS="-lcxml"])
+ fi
+ 
+ # BLAS in Alpha DXML library? (now called CXML, see above)
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(dxml, $sgemm, [acx_blas_ok=yes;BLAS_LIBS="-ldxml"])
+ fi
+ 
+ # BLAS in Sun Performance library?
+ if test $acx_blas_ok = no; then
+         if test "x$GCC" != xyes; then # only works with Sun CC
+                 AC_CHECK_LIB(sunmath, acosp,
+                         [AC_CHECK_LIB(sunperf, $sgemm,
+                                 [BLAS_LIBS="-xlic_lib=sunperf -lsunmath"
+                                  acx_blas_ok=yes],[],[-lsunmath])])
+         fi
+ fi
+ 
+ # BLAS in SCSL library?  (SGI/Cray Scientific Library)
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(scs, $sgemm, [acx_blas_ok=yes; BLAS_LIBS="-lscs"])
+ fi
+ 
+ # BLAS in SGIMATH library?
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(complib.sgimath, $sgemm,
+                      [acx_blas_ok=yes; BLAS_LIBS="-lcomplib.sgimath"])
+ fi
+ 
+ # BLAS in IBM ESSL library? (requires generic BLAS lib, too)
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(blas, $sgemm,
+                 [AC_CHECK_LIB(essl, $sgemm,
+                         [acx_blas_ok=yes; BLAS_LIBS="-lessl -lblas"],
+                         [], [-lblas $FLIBS])])
+ fi
+ 
+ # Generic BLAS library?
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(blas, $sgemm, [acx_blas_ok=yes; BLAS_LIBS="-lblas"])
+ fi
+ 
+ if test $acx_blas_ok = no; then
+         AC_CHECK_LIB(blas, $sgemm, [acx_blas_ok=yes; BLAS_LIBS="-lblas $FCLIBS"])
+ fi
+ 
+ fi # if BLAS_LIBS=builtin
+ 
+ AC_SUBST(BLAS_LIBS)
+ 
+ LIBS="$acx_blas_save_LIBS"
+ 
+ # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+ if test x"$acx_blas_ok" = xyes; then
+ 	echo "OK, You have working BLAS libs ! Using $BLAS_LIBS" ; HAVE_VENDOR_BLAS=1
+ else
+         echo " *** YOU DONT HAVE BLAS! *** Using a cheap replacement" ; HAVE_VENDOR_BLAS=0
+ fi
+ 
+ dnl ACX_BLAS([ echo "OK, You have working BLAS libs !"; HAVE_VENDOR_BLAS=1 ], [echo "YOU DONT HAVE BLAS! Using a cheap replacement" ; HAVE_VENDOR_BLAS=0])
+ LIBS="$LIBS $BLAS_LIBS"
+ CPPFLAGS="$CPPFLAGS -DGMM_USES_BLAS"
+ 
+ 
+ dnl ------------------------------SuperLU config-------------------------
+ AC_ARG_ENABLE(superlu,
+  [AS_HELP_STRING([--enable-superlu],[turn on/off SuperLU support])],
+  [case "${enableval}" in
+    yes) usesuperlu=YES ;;
+    no)  usesuperlu=NO ;;
+    *) AC_MSG_ERROR([bad value ${enableval} for --enable-superlu]) ;;
+  esac],[usesuperlu=YES])
+ 
+ SUPERLU_CPPFLAGS=""
+ SUPERLU_SRC=""
+ SUPERLU_LIBS=""
+ SUPERLU_MAKEFILE=""
+ 
+ if test x$usesuperlu = xYES; then
+   echo "Building with SuperLU support (use --enable-superlu=no to disable it)"
+   if test x"$FC" = "x"; then
+     sgemm="sgemm_"
+   else
+     AC_FC_FUNC(sgemm)
+     echo "FC=$FC"
+   fi
+   case $sgemm in
+     sgemm)
+           F77_CALL_C="NOCHANGE";
+           ;;
+     sgemm_)
+           F77_CALL_C="ADD_";
+           ;;
+     SGEMM)
+           F77_CALL_C="UPCASE";
+           ;;
+     sgemm__)
+           F77_CALL_C="ADD__";
+           ;;
+     *)
+           AC_MSG_ERROR(["superlu won't handle this calling convention: sgemm -> $sgemm"])
+           ;;
+   esac
+   SUPERLU_CPPFLAGS="$CPPFLAGS -DUSE_VENDOR_BLAS -DF77_CALL_C=$F77_CALL_C"
+   SUPERLU_SRC="superlu"
+   case $host in
+     *apple*)
+         SUPERLU_LIBS="../$SUPERLU_SRC/libsuperlu.la"
+         ;;
+     *)
+         SUPERLU_LIBS="`readlink -f .`/$SUPERLU_SRC/libsuperlu.la"
+         ;;
+   esac
+   SUPERLU_MAKEFILE="$SUPERLU_SRC/Makefile"
+ else
+   echo "Building without SuperLU support (use --enable-superlu=yes to enable it)"
+   AC_CHECK_LIB([superlu], [dCreate_CompCol_Matrix],[],
+                [AC_MSG_ERROR([SuperLU library not found])])
+ 
+   AC_CHECK_HEADERS(
+   [superlu/colamd.h superlu/slu_Cnames.h \
+    superlu/slu_cdefs.h superlu/slu_ddefs.h superlu/slu_sdefs.h superlu/slu_zdefs.h \
+    superlu/slu_dcomplex.h superlu/slu_scomplex.h],
+   [usesuperlu="YES"],
+   [
+     if test "x$usesuperlu" = "xYES"; then
+       AC_MSG_ERROR([header files of superlu not found. Use --enable-superlu=yes flag]);
+     fi;
+   ])
+ 
+   SUPERLU_LIBS="-lsuperlu"
+   LIBS="$LIBS $SUPERLU_LIBS"
+ fi
+ 
+ AC_SUBST([SUPERLU_CPPFLAGS])
+ AC_SUBST([SUPERLU_SRC])
+ AC_SUBST([SUPERLU_LIBS])
+ AM_CONDITIONAL(USEBLASLITE, test x$HAVE_VENDOR_BLAS = x0)
+ echo "Configuration of SuperLU done"
+ 
+ 
+ dnl ----------------EXPERIMENTAL PARTS OF THE LIBRARY--------------------
+ EXPER=""
+ AC_ARG_ENABLE(experimental,
+         [AS_HELP_STRING([--enable-experimental],[compile experimental parts of the library])],
+ [ if   test "x$enableval" = "xyes" ; then EXPER="-DEXPERIMENTAL_PURPOSE_ONLY"; fi], [EXPER=""])
+ CPPFLAGS="$CPPFLAGS $EXPER"
+ 
+ dnl -----------------------------QD TESTS--------------------------------
+ AC_ARG_WITH(qd-lib-dir,
+         [AS_HELP_STRING([--with-qd-lib-dir],[directory in which the libqd.a can be found])],
+ 	QDLIB="$withval/libqd.a",QDLIB="$GFPREFIX/lib/libqd.a")
+ AC_ARG_WITH(qd-include-dir,
+         [AS_HELP_STRING([--with-qd-include-dir],[directory in which the qd.h header can be found])],
+ 	QDINC="-I$withval",QDINC="-I$GFPREFIX/include")
+ AC_ARG_ENABLE(dd,
+  [AS_HELP_STRING([--enable-dd],[enable the use of the qd library (some computation will be done with double-double precision, useful for high order FEMs)])],
+  [ if   test "x$enableval" = "xyes" ; then useQDlib="yes"; QD_PREC="double"; fi], [useQDlib="no"])
+ AC_ARG_ENABLE(qd,
+  [AS_HELP_STRING([--enable-qd],[enable the use of the qd library (some computation will be done with quad-double precision, useful for high order FEMs)])],
+  [ if   test "x$enableval" = "xyes" ; then useQDlib="yes"; QD_PREC="quad"; fi], [if test "x$useQDlib" = "xyes"; then useQDlib="yes"; else useQDlib="no"; fi])
+ if test "x$useQDlib" = "xyes" ; then  
+   LIBS="$LIBS $QDLIB -lm"
+   CPPFLAGS="$CPPFLAGS $QDINC"
+ dnl #define NO_INLINE
+   AC_RUN_IFELSE([AC_LANG_SOURCE([[
+ #include <qd/qd_real.h>
+ #include <qd/dd_real.h>
+ #include <qd/fpu.h>
+ #include <iostream>
+ int main() {
+   unsigned int old_cw;
+   int ok;
+   fpu_fix_start(&old_cw);
+   qd_real q = 1.0;
+   qd_real qq = qd_real("0.01");
+   qd_real qqq = "1.010101010101010101010101010101010101010101010101010101010101010E0";
+   dd_real d = 1.0;
+   dd_real dd = dd_real("0.1");
+   dd_real ddd = "1.1111111111111111111111111111111E0";
+   for (int i=0; i < 100; ++i) { d += dd; dd *= dd_real("0.1"); }
+   for (int i=0; i < 100; ++i) { q += qq; qq *= qd_real("0.01"); }
+   std::cerr << "d = " << d << std::endl << "q = " << q << std::endl;
+   std::cerr << abs(q - qqq) << std::endl;
+   std::cerr << abs(d - ddd) << std::endl;
+   if (abs(q - qqq) < 1e-63 && abs(d -ddd) < 1e-31) ok = 1;
+   else ok = 0;
+   fpu_fix_end(&old_cw); return 1-ok;
+ }
+   ]])],[echo "checking if qd library is working...yes"],[ echo "QD library is not working (check config.log)"; exit 1],[])
+   AC_DEFINE_UNQUOTED([HAVE_QDLIB],1,[defined if the qd library was found and is working])
+   HAVE_QDLIB=1;
+   if test "x$QD_PREC" = "xquad"; then
+     AC_DEFINE_UNQUOTED([QDLIB_USE_QUAD],1,[defined if quad-doubles are to be used instead of double-double])
+   fi;
+ fi;
+ dnl -----------------------------END QD TESTS--------------------------------
+ 
+ dnl ------------------------------QHULL TEST---------------------------------
+ useQHULL="no"
+ AC_ARG_ENABLE(qhull,
+  [AS_HELP_STRING([--enable-qhull],[enable the use of the qhull library (required for generation of non regular meshes)])],
+  [ if   test "x$enableval" = "xyes" ; then useQHULL="yes"; fi], [useQHULL="test"])
+ QHULL_LIBS=""
+ 
+ if test "x$useQHULL" = "xno"; then
+   echo "Building with libqhull explicitly disabled";
+ else
+   AC_CHECK_LIB(qhull, qh_new_qhull)
+   AC_CHECK_HEADERS(qhull/qhull.h,[useQHULL="yes"],
+   [
+     if test "x$useQHULL" = "xyes"; then
+       AC_MSG_ERROR([header files qhull/qhull.h not found. Use --enable-qhull=no flag]);
+       useQHULL="no"
+     fi;
+   ])
+   if test "x$useQHULL" = "xyes"; then
+     QHULL_LIBS="-lqhull"
+   fi;
+   echo "Building with libqhull (use --enable-qhull=no to disable it)"
+ fi;
+ AM_CONDITIONAL(QHULL, test x$useQHULL = xyes)
+ 
+ AC_SUBST([QHULL_LIBS])
+ echo "Configuration of qhull done"
+ dnl -----------------------------END OF QHULL TEST---------------------------
+ 
+ dnl ------------------------------MUPARSER------------------------------
+ MUPARSERSINC=""
+ AC_ARG_WITH(muparser-include-dir,
+  [AS_HELP_STRING([--with-muparser-include-dir],[directory in which the muParser.h header can be found])],
+  [case $withval in
+    -I* ) MUPARSERINC="$withval";;
+    * ) MUPARSERINC="-I$withval";;
+   esac],
+  [MUPARSERINC="-I$GFPREFIX/include"]
+ )
+ CPPFLAGS="$CPPFLAGS $MUPARSERINC"
+ dnl ---------------------------END OF MUPARSER--------------------------
+ 
+ dnl ------------------------------MUPARSER TEST------------------------------
+ usemuparser="no"
+ AC_ARG_ENABLE(muparser,
+  [AS_HELP_STRING([--enable-muparser],[enable the use of the muParser library (required for parsing mathematical expressions)])],
+  [ if test "x$enableval" = "xyes" ; then usemuparser="yes"; fi], [usemuparser="test"])
+ MUPARSER_LIBS=""
+ 
+ if test "x$usemuparser" = "xno"; then
+   echo "Building with muParser explicitly disabled";
+ else
+   AC_CHECK_LIB(muparser, _init, [], [AC_CHECK_LIB(muparser, mupEval)])
+    AC_CHECK_HEADERS(muParser/muParser.h, [usemuparser="yes"],
+    [ 
+      AC_CHECK_HEADERS(muParser.h, [usemuparser="yes"],
+      [
+      if test "x$usemuparser" = "xyes"; then
+      	AC_MSG_ERROR([header file muParser.h or muParser/muParser.h not found. Use --enable-muparser=no flag]);
+ 	usemuparser="no"
+    	fi;
+      ])
+    ])
+ 
+   if test "x$usemuparser" = "xyes"; then
+     MUPARSER_LIBS="-lmuparser"
+   fi;
+   echo "Building with muParser (use --enable-muparser=no to disable it)"
+ fi;
+ 
+ AM_CONDITIONAL(MUPARSER, test x$usemuparser = xyes)
+ AC_SUBST([MUPARSER_LIBS])
+ echo "Configuration of muParser done"
+ dnl ---------------------------END OF MUPARSER TEST--------------------------
+ 
+ dnl ------------------------------MUMPS TEST------------------------------
+ MUMPSINC=""
+ AC_ARG_WITH(mumps-include-dir,
+  [AS_HELP_STRING([--with-mumps-include-dir],[directory in which the dmumps.h header can be found])],
+  [case $withval in
+    -I* ) MUMPSINC="$withval";;
+    * ) MUMPSINC="-I$withval";;
+   esac],
+  [MUMPSINC="-I$GFPREFIX/include"]
+ )
+ CPPFLAGS="$CPPFLAGS $MUMPSINC"
+ 
+ MUMPS_LIBS=""
+ acx_mumps_ok="no"
+ usemumps="no"
+ AC_ARG_ENABLE(mumps,
+  [AS_HELP_STRING([--enable-mumps],[enable the use of the (sequential) MUMPS library. A direct solver for large sparse linear systems.])],
+  [case $enableval in
+    yes | "") usemumps="yes"; acx_mumps_ok="yes"; MUMPS_LIBS="-lsmumps_seq -ldmumps_seq -lcmumps_seq -lzmumps_seq";;
+    no) usemumps="no";;
+   esac],
+  [usemumps="test"; acx_mumps_ok="test"; MUMPS_LIBS="-lsmumps_seq -ldmumps_seq -lcmumps_seq -lzmumps_seq"]
+ )
+ 
+ AC_ARG_ENABLE(par-mumps,
+  [AS_HELP_STRING([--enable-par-mumps],[enable the use of the parrallel MUMPS library. A direct solver for large sparse linear systems.])],
+  [case $enableval in
+    yes | "") usemumps="yes"; MUMPS_LIBS="-lsmumps -ldmumps -lcmumps -lzmumps";;
+    no) usemumps="no";;
++<<<<<<< HEAD:configure.in
++  esac]
++=======
+   esac],
+  [if test $paralevel -ge 1; then
+     usemumps="test"; acx_mumps_ok="test"; MUMPS_LIBS="-lsmumps -ldmumps -lcmumps -lzmumps"
+   fi;]
++>>>>>>> upstream:configure.ac
+ )
+ 
+ AC_ARG_WITH(mumps,
+  [AS_HELP_STRING([--with-mumps=<lib>],[use MUMPS library <lib>])],
+  [case $with_mumps in
+    yes | "") usemumps="yes";;
+    no) acx_mumps_ok="no" ;;
+    -* | */* | *.a | *.so | *.so.* | *.o| builtin) MUMPS_LIBS="$with_mumps"; acx_mumps_ok="yes" ;;
+    *) MUMPS_LIBS=`echo $with_mumps | sed -e 's/^/-l/g;s/ / -l/g'` ; usemumps="yes";;
+   esac]
+ )
+ 
+ 
+ if test "x$usemumps" = "xno" -o "x$acx_mumps_ok" = "xno"; then
+   echo "Building with MUMPS explicitly disabled";
+ else
+  AC_SEARCH_LIBS(smumps_c, [`echo $MUMPS_LIBS | sed -e 's/^-l//g;s/ -l/ /g'`],
+    [usemumps="yes"],
+    [if test "x$acx_mumps_ok" = "xyes"; then
+      AC_MSG_ERROR([The function smumps_c couldn't be found in the provided MUMPS libraries.]);
+     fi;
+     usemumps="no"]
+  )
+  AC_SEARCH_LIBS(dmumps_c, [`echo $MUMPS_LIBS | sed -e 's/^-l//g;s/ -l/ /g'`],
+    [usemumps="yes"],
+    [if test "x$acx_mumps_ok" = "xyes"; then
+      AC_MSG_ERROR([The function dmumps_c couldn't be found in the provided MUMPS libraries.]);
+     fi;
+     usemumps="no"]
+  )
+  AC_SEARCH_LIBS(cmumps_c, [`echo $MUMPS_LIBS | sed -e 's/^-l//g;s/ -l/ /g'`],
+    [usemumps="yes"],
+    [if test "x$acx_mumps_ok" = "xyes"; then
+      AC_MSG_ERROR([The function cmumps_c couldn't be found in the provided MUMPS libraries.]);
+     fi;
+     usemumps="no"]
+  )
+  AC_SEARCH_LIBS(zmumps_c, [`echo $MUMPS_LIBS | sed -e 's/^-l//g;s/ -l/ /g'`],
+    [usemumps="yes"],
+    [if test "x$acx_mumps_ok" = "xyes"; then
+      AC_MSG_ERROR([The function zmumps_c couldn't be found in the provided MUMPS libraries.]);
+     fi;
+     usemumps="no"]
+  )
+  AC_CHECK_HEADERS([smumps_c.h dmumps_c.h cmumps_c.h zmumps_c.h],
+    [usemumps="yes"],
+    [if test "x$acx_mumps_ok" = "xyes"; then
+      AC_MSG_ERROR([header file dmumps_c.h not found.]);
+     fi;
+     usemumps="no"]
+  )
+ 
+  if test "x$usemumps" = "xyes"; then
+    echo "Building with MUMPS (use --enable-mumps=no to disable it)"
+  else
+    MUMPS_LIBS=""
+  fi;
+ fi;
+ 
+ AM_CONDITIONAL(MUMPS, test x$usemumps = xyes)
+ AC_SUBST([MUMPS_LIBS])
+ echo "Configuration of MUMPS done"
+ dnl ---------------------------END OF MUMPS TEST--------------------------
+ 
+ dnl ---------------------------METIS--------------------------
++<<<<<<< HEAD:configure.in
++usemetis="no"
++if test $paralevel -ge 2; then
++  usemetis="yes"
++fi;
++
++METIS_LIBS=""
++AC_ARG_ENABLE(metis,
++ [AS_HELP_STRING([--enable-metis],[enable the use of the METIS library.])],
++ [case $enableval in
++   yes | "") usemetis="yes" ;;
++   no) usemetis="no"; METIS_LIBS="" ;;
++  esac],
++ [usemetis="test"]
++)
++
++if test "x$usemetis" = "xno"; then
++  echo "Building without METIS";
++else
++  AC_CHECK_LIB(metis, SelectQueueOneWay, [usemetis="yes"], [usemetis="no"])
++dnl  AC_CHECK_HEADERS(metis.h, [usemetis="yes"],
++dnl    [ 
++dnl      AC_MSG_ERROR([header file metis.h not found]);
++dnl      usemetis="no"
++dnl    ])
++=======
+ METIS_LIBS=""
+ AC_ARG_ENABLE(metis,
+  [AS_HELP_STRING([--enable-metis],[enable the use of the METIS library.])],
+  [case $enableval in
+    yes | "") usemetis="yes" ;;
+    no) usemetis="no"; METIS_LIBS="" ;;
+   esac],
+  [usemetis="test"]
+ )
+ 
+ if test $paralevel -ge 2 -a "x$usemetis" = "xno"; then
+   echo "Parallel getfem requires the METIS library, --enable-metis=no will be ignored";
+   usemetis="yes"
+ fi;
+ 
+ if test "x$usemetis" = "xno"; then
+   echo "Building without METIS";
+ else
+   AC_CHECK_LIB(metis, METIS_PartGraphRecursive,
+                [usemetis="yes"],
+                [usemetis="no";
+                 if test $paralevel -ge 2; then
+                   AC_MSG_ERROR([METIS library required for parallel getfem was not found])
+                 fi
+                ])
+ dnl  AC_CHECK_HEADERS(metis.h,
+ dnl                   [usemetis="yes"],
+ dnl                   [usemetis="no";
+ dnl                    if test $paralevel -ge 2; then
+ dnl                      AC_MSG_ERROR([metis.h header required for parallel getfem was not found])
+ dnl                    fi
+ dnl                   ])
++>>>>>>> upstream:configure.ac
+ 
+   if test "x$usemetis" = "xyes"; then
+     METIS_LIBS="-lmetis"
+     LIBS="$LIBS $METIS_LIBS"
+     AC_DEFINE_UNQUOTED([HAVE_METIS],1,[defined if the Metis library was found and is working])
+     echo "Building with METIS (use --enable-metis=no to disable it)"
+   else
++<<<<<<< HEAD:configure.in
++    echo "Building without METIS";
++=======
+     echo "METIS library could not be found, building without METIS";
++>>>>>>> upstream:configure.ac
+   fi;
+ fi;
+ 
+ AM_CONDITIONAL(METIS, test x$usemetis = xyes)
+ AC_SUBST([METIS_LIBS])
+ 
+ 
+ dnl ---------------------------END OF METIS--------------------------
+ 
+ 
++<<<<<<< HEAD:configure.in
++dnl ---------------------------MPI--------------------------
++
++usempi="no"
++MPI_LIBS=""
++
++if test $paralevel -ge 2; then
++  usempi="yes"
++  MPI_LIBS=""
++  AC_CHECK_LIB(mpich, MPI_Test)
++  AC_CHECK_LIB(mpichcxx, MPI_Test)
++dnl   AC_CHECK_HEADERS(mpi/mpi.h, [usempi="yes"],
++dnl    [ 
++dnl      AC_CHECK_HEADERS(mpi.h, [usempi="yes"],
++dnl      [
++dnl        AC_CHECK_HEADERS(mpich2/mpi.h, [usempi="yes"],
++dnl        [
++dnl          if test "x$usempi" = "xyes"; then
++dnl      	   AC_MSG_ERROR([header file mpi.h not found.]);
++dnl 	   usempi="no"
++dnl    	 fi;
++dnl        ])
++dnl      ])
++dnl    ])
++  CPPFLAGS="$CPPFLAGS -DGETFEM_HAVE_MPI_MPI_H=1 -I/usr/include/mpi"
++  if test "x$usempi" = "xyes"; then
++    MPI_LIBS="-lmpi -lmpi++"
++  fi;
++  echo "Building with MPI (use --enable-mpi=no to disable it)"
++fi;
++
++AM_CONDITIONAL(MPI, test x$usempi = xyes)
++AC_SUBST([MPI_LIBS])
++
++
++dnl ---------------------------END OF MPI--------------------------
++
++
++=======
++>>>>>>> upstream:configure.ac
+ dnl ------------------------------LAPACK TEST--------------------------------
+ 
+ if test x"$acx_blas_ok" = xyes; then
+   if test x"$FC" = "x"; then
+     dgetrf=dgetrf_
+   else
+     AC_FC_FUNC(dgetrf)
+   fi;
+ 
+   AC_CHECK_LIB(lapack, dgetrf_, [acx_lapack_ok=yes; LAPACK_LIBS="-llapack "])
+ 
+   if test x"$acx_lapack_ok" = xyes; then
+      CPPFLAGS="$CPPFLAGS -DGMM_USES_LAPACK"
+      LIBS="$LIBS $LAPACK_LIBS"
+   fi
+ fi
+ 
+ dnl -----------------------------END OF LAPACK TEST--------------------------
+ 
+ 
++<<<<<<< HEAD:configure.in
++dnl ------------------------------MPI TEST--------------------------------
++if test "$MPI_CFLAGS" -o "$MPI_LIBS"; then
++  echo "You are using MPI! Trying to build a parallelised version of getfem (require METIS)"
++  dnl AC_DEFINE_UNQUOTED([PARA_LEVEL], 2, [getfem parallelisation flag])
++  LIBS="$LIBS $MPI_LIBS -lmetis"
++  CXXFLAGS="$CXXFLAGS $MPI_CFLAGS -DGETFEM_PARA_LEVEL=2"
++dnl   AC_CHECK_LIB(metis, METIS_PartMeshNodal, [metis_ok="yes"], [metis_ok="no"])
++dnl   if test "x$metis_ok" = "xno"; then
++dnl     AC_MSG_ERROR([Parallel getfem requires the METIS ( http://www-users.cs.umn.edu/~karypis/metis/metis/ ) library
++dnl  ----------> Please add the path to libmetis.a to the MPI_LIBS variable.])
++dnl   fi
++  AC_SUBST(MPI_LIBS)
++  AC_SUBST(MPI_CFLAGS)
++fi
++
++
++dnl -----------------------------END OF MPI TEST--------------------------
++
++
++=======
++>>>>>>> upstream:configure.ac
+ AC_CHECK_HEADERS(sys/times.h,[],[SUPERLU_CPPFLAGS="$SUPERLU_CPPFLAGS -DNO_TIMER"])
+ AC_CHECK_HEADERS(cxxabi.h)
+ dnl ---------------------------- CHECK FOR __PRETTY_FUNCTION__ MACRO --------
+ AC_CACHE_CHECK([for __PRETTY_FUNCTION__], ac_cv_have_pretty_function, [
+         AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [
+                 [ const char *s = __PRETTY_FUNCTION__; ]])],
+                 [ ac_cv_have_pretty_function="yes" ],
+                 [ ac_cv_have_pretty_function=="no"  ])])
+ if test "x$ac_cv_have_pretty_function" = "xyes"; then
+         AC_DEFINE_UNQUOTED(HAVE_PRETTY_FUNCTION,1,[gcc style __PRETTY_FUNCTION__ macro])
+ fi;     
+ 
+ 
+ dnl ---------------------------- CHECK FOR GLIBC BACKTRACE availability -----
+ AC_CACHE_CHECK([for execinfo.h and backtrace], ac_cv_have_backtrace, [
+         AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+                 [[ #include <execinfo.h>  ]],
+                 [[ void* trace[256]; int n = backtrace(trace, 256); ]])],
+                 [ ac_cv_have_backtrace="yes" ],
+                 [ ac_cv_have_backtrace="no"  ])])
+ if test "x$ac_cv_have_backtrace" = "xyes"; then
+         AC_DEFINE_UNQUOTED(HAVE_BACKTRACE,1,[glibc backtrace function])
+ fi;     
+ 
+ dnl ---------------------------- CHECK FOR feenableexcept -----
+ AC_CACHE_CHECK([for fenv.h and feenableexcept], ac_cv_have_feenableexcept, [
+         AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+                 [[ #include <fenv.h>           ]], 
+                 [[ feenableexcept(FE_DIVBYZERO | FE_INVALID); ]])],
+                 [ ac_cv_have_feenableexcept="yes" ],
+                 [ ac_cv_have_feenableexcept="no"  ])])
+ if test "x$ac_cv_have_feenableexcept" = "xyes"; then
+         AC_DEFINE_UNQUOTED(HAVE_FEENABLEEXCEPT,1,[glibc floating point exceptions control])
+ fi;
+ 
+ BUILDER=`whoami`
+ AC_SUBST(BUILDER)
+ BUILDDATE=`date +%D,%H:%M:%S`
+ AC_SUBST(BUILDDATE)
+ CONFIGURE_ARGS=$ac_configure_args
+ AC_SUBST(CONFIGURE_ARGS)
+ LIBTOOL_VERSION_INFO="-version-info ${MAJOR_VERSION}:${MINOR_VERSION}:0"
+ AC_SUBST(LIBTOOL_VERSION_INFO)
+ 
+ dnl AC_CHECK_PROGS(RANLIB, ranlib)
+ 
+ 
+ dnl ------------ for distclean of meshes ---------------------
+ j="tests/meshes/disc_P2_h4.mesh"
+ if test -L $j || test ! -f $j; then
+   DISTCLEANMESH="";
+ else
+   DISTCLEANMESH="#";
+ fi;
+ AC_SUBST(DISTCLEANMESH)
+ 
+ 
+ dnl -----------------------------------------------
+ dnl switch for using the getfem_boost supplied files, or the real boost
+ dnl -----------------------------------------------
+ 
+ AC_ARG_ENABLE(boost,
+  [AS_HELP_STRING([--enable-boost],[assume that boost is installed and use it])],
+  [case "${enableval}" in
+   yes) useboost=YES ;;
+   no)  useboost=NO ;;
+   *) AC_MSG_ERROR([bad value ${enableval} for --enable-boost]) ;;
+  esac],[useboost=NO])
+ 
+ if test "x$useboost" = "xYES"; then
+         AC_DEFINE_UNQUOTED(HAVE_BOOST,1,[Tell getfem to use the real boost library])
+ fi;
+ 
+ 
+ dnl -----------------------------------------------
+ dnl MATLAB Interface
+ dnl -----------------------------------------------
+ 
+ # list of pseud functions
+ PSEUDO_FUNCTIONS_LOC=`$srcdir/bin/extract_doc $srcdir/interface/src pseudo_loc`
+ PSEUDO_FUNCTIONS=`$srcdir/bin/extract_doc $srcdir/interface/src pseudo_gen`
+ MATLAB_OBJ_DIRS=`$srcdir/bin/extract_doc $srcdir/interface/src mobj_dirs`
+ AC_SUBST(PSEUDO_FUNCTIONS)
+ AC_SUBST(PSEUDO_FUNCTIONS_LOC)
+ AC_SUBST(MATLAB_OBJ_DIRS)
+ 
+ AC_ARG_ENABLE(matlab,
+  [AS_HELP_STRING([--enable-matlab],[turn on/off matlab support])],
+  [case "${enableval}" in
+    yes) usematlab=YES ;;
+    no)  usematlab=NO ;;
+    *) AC_MSG_ERROR([bad value ${enableval} for --enable-matlab]) ;;
+  esac],[usematlab=NO])
+ 
+ AC_ARG_WITH(matlab-toolbox-dir,
+             [AS_HELP_STRING([--with-matlab-toolbox-dir],[directory in which the matlab interface will be installed])],
+             TOOLBOXDIR="$withval",TOOLBOXDIR="$GFPREFIX/getfem_toolbox")
+ AC_SUBST(TOOLBOXDIR)
+ 
+ AC_ARG_ENABLE(python,
+  [AS_HELP_STRING([--enable-python],[turn on/off python support])],
+  [case "${enableval}" in
+    yes) usepython=YES ;;
+    no)  usepython=NO ;;
+    *) AC_MSG_ERROR([bad value ${enableval} for --enable-python]) ;;
+  esac],[usepython=YES])
+ 
+ if test "$usematlab" != NO; then
+   AC_CHECK_PROGS(MEX, mex)
+   if test x"$MEX" = x""; then
+     AC_CHECK_PROGS(MEX, mex.bat)
+     if test x"$MEX" = x""; then
+       if test x$usematlab = xYES; then
+         AC_MSG_ERROR([Impossible to build the matlab interface without mex -- specify its full path with the MEX=/path/to/mex option, or use --enable-matlab-interface=no])
+         exit 1
+       fi
+     else
+       MEX=gnumex;
+       MATLAB_COM_EXT=".dll";
+       echo "You are using Matlab on a windows platform (assuming MingW compiler)";
+       if test -f gnumex.opts; then
+          echo "sourcing gnumex.opts.."
+          source gnumex.opts;         
+          echo "MATLAB_ROOT=$MATLAB_ROOT"
+          echo "Matlab release is : R$MATLAB_RELEASE"
+       elif test x$usematlab = xYES; then
+         echo "You need to fill the gnumex.opts file, for example (use MSys-style paths, not DOS-style paths)"
+         echo '#!/bin/sh'
+         echo 'MATLAB_ROOT="c:\\MATLAB6p5"'
+         echo 'MATLAB_RELEASE=13'
+         echo 'MATLAB_INC_DIR="$MATLAB_ROOT\\extern\\include"'
+         echo 'MEXOPTS=c:\\gnumex\\mexopts.bat'
+         echo "when this is done, check that the gnumex script works correctly"
+         echo " (i.e. gnumex gnumex.opts -v prints the rights options to use the MinGW gcc)"
+         exit 1
+       fi
+     fi
+   else
+      dnl thanks to paolo for pointing the 'twin mex' problem
+      if $(echo "" | $MEX 2>&1 | grep 'This is .*TeX'); then
+ 	  AC_MSG_ERROR([the mex binary which is in the PATH appears to be part of LaTeX, not matlab !! run ./configure MEX=/path/to/matlab/mex]);
+      fi;
+      MATLAB_ROOT=`$MEX -v 2>&1 | grep "MATLAB " | awk '{print $4}'|sed -e '2,$d'`
+      MATLAB_INC_DIR=$MATLAB_ROOT/extern/include
+      echo "checking for matlab path... " $MATLAB_ROOT
+      MATLAB_COM_EXT=`$MEX -v 2>&1 | grep "LDEXTENSION " | awk '{print $3}'`
+      echo "checking for mex extension... " $MATLAB_COM_EXT
+ #    MATLAB_RELEASE=`grep "MATLAB R" $MATLAB_ROOT/extern/src/mexversion.c | awk '{print $4}' | sed -e 's/R//'`
+      MATLAB_RELEASE=`grep "full_ver=" $(which $MEX) | sed 's/[[^0-9]]//g'` # double brackets are for escaping reasons.
+      echo "Matlab release is : R$MATLAB_RELEASE"
+   fi
+ fi
+ AM_CONDITIONAL(BUILDMEX, test x$usematlab = xYES)
+ 
+ 
+ 
+ AC_SUBST(MATLAB_ROOT)
+ AC_SUBST(MATLAB_INC_DIR)
+ AC_SUBST(MATLAB_RELEASE)
+ AC_SUBST(MATLAB_COM_EXT)
+ AC_SUBST(MEX)
+ 
+ AM_CONDITIONAL(USE_MINGW_MEX, test x"$MATLAB_COM_EXT" = x".dll")
+ 
+ 
+ 
+ dnl ----------------------------
+ dnl RPCs -- matlab interface communication with a separated getfem process
+ dnl useful for debugging..
+ GETFEM_SERVER="";
+ use_rpc="no";
+ AC_ARG_ENABLE(matlab-rpc,
+  [AS_HELP_STRING([--enable-matlab-rpc],[enable use of RPCs for matlab interface])],
+  [ matlab_rpc="yes"; use_rpc="yes";
+    echo "Matlab mex-file will use sun RPCs in order to communicate with the getfem server"],
+  [matlab_rpc="no"])
+ 
+ if test x$use_rpc = xyes; then
+   GETFEM_SERVER="getfem_server";
+   AC_ARG_WITH(rpc-include,
+               [AS_HELP_STRING([--with-rpc-include],[directory in which the rpc/rpc.h header can be found])],
+               RPC_INC_DIR="-I$withval",RPC_INC_DIR="")
+   case $host in
+         *alpha*)
+                 RPC_LIB="-lrpc";
+                 ;;
+ 	*darwin*)
+ 	        RPC_LIB="";
+ 		;;
+         *)
+                 RPC_LIB="-lnsl";
+                 ;;
+   esac
+   AC_ARG_WITH(rpc-lib,
+               [AS_HELP_STRING([--with-rpc-lib],[linker flags for the RPC library])],
+               RPC_LIB="$withval")
+   AC_SUBST(RPC_INC_DIR)
+   AC_SUBST(RPC_LIB)
+   AC_DEFINE_UNQUOTED(USE_RPC, 1, [Use rpc for getfem communication with matlab])
+ fi;
+ AC_SUBST(GETFEM_SERVER)
+ AM_CONDITIONAL(BUILDMEXRPC, test x$matlab_rpc = xyes)
+ 
+ 
+ dnl the pb is that we cannot link the libstdc++.so in the mex-file without horrible problems
+ dnl with dynamic_casts (with matlab 6.5 -- the pb seems to have disappeared since matlab-7). 
+ dnl Hence the gf_matlab.mexglx should be linked against the libstdc++.a ..
+ STDCPP_STATICLIBS=""
+ 
+ if test $usematlab = xYES; then
+   dnl ------------------------------------
+   dnl COMPILER SETTINGS
+   compiler_type=dontcare
+   case $CXX in
+    *g++* | c++)
+ 	case $host in
+ 	x86_64-*)
+ 	       echo "Compiling on an x86_64 architecture..."
+ 	       ;;
+         *-darwin*)
+                echo "Compiling on Darwin (MacOS)"
+ 		;;
+ 	*)
+ 		STDCPP_STATICLIBS=$($CXX -print-file-name=libstdc++.a)
+ 		echo "The MEX file will be linked against the static c++ library '$STDCPP_STATICLIBS'"
+ 		;;
+ 	esac
+ 	;;
+    *icc | *icpc)
+ 	dnl a small remark: with icpc 8.0, the getfem_server will crash 
+ 	dnl at the first exception throwed (except with -g)
+ 	dnl the fix is to pass the -static flag at the linker
+ 	dnl unfortunately, the lovely libtool assumes that icpc won't
+ 	dnl understand it, and removes it. I hate libtool.
+ 	dnl so I added the -Wl,-static -- it works for now.
+ 	GFSERVERFLAGS="-Wl,-static -static"
+ 	;;
+    *)
+ 	;;
+   esac
+ fi
+ AC_SUBST(GFSERVERFLAGS)
+ AC_SUBST(STDCPP_STATICLIBS)
+ 
+ 
+ 
+ dnl ----------------------------------------------
+ dnl python 
+ dnl ----------------------------------------------
+ 
+ if test x$usepython = xYES; then
+   AM_PATH_PYTHON(2.2, usepython=YES, usepython=NO)
+ fi
+ 
+ AM_CONDITIONAL(BUILDPYTHON, test x$usepython = xYES)
+ 
+ if test x$usepython = xYES; then
+   echo "Building with python support (use --enable-python=no to disable it)"
+   echo "You will need the python-numpy and python-scipy packages."
+ dnl  AM_PATH_PYTHON(2.2)
+   AC_PYTHON_DEVEL
+ fi
+ 
+ 
+ dnl -----------------------------------------------
+ dnl SCILAB Interface
+ dnl -----------------------------------------------
+ 
+ m4_include([m4/scilab.m4])
+ 
+ REQUIRED_SCILAB_MAJOR=5
+ REQUIRED_SCILAB_MINOR=2
+ REQUIRED_SCILAB_MICRO=0
+ 
+ AC_CHECK_SCILAB
+ 
+ GETFEM_INTERFACE_PATH="`readlink -f $srcdir`"
+ GETFEM_BUILD_INTERFACE_PATH="`readlink -f $PWD`"
+ AC_SUBST(GETFEM_INTERFACE_PATH)
+ AC_SUBST(GETFEM_BUILD_INTERFACE_PATH)
+ 
+ dnl if the scilab directory doesn't exists, we copy the 
+ dnl scilab sources into the build directory
+ 
+ if test "x$usescilab" == "xYES"
+ then
+   currentdir=`pwd`
+   if test ! -f $currentdir/interface/src/scilab/builder.sce
+   then
+     echo "Copying Scilab toolbox src in the build directory"
+     mkdir -p $currentdir/interface/src/scilab/
+     cp -r $srcdir/interface/src/scilab/* $currentdir/interface/src/scilab
+   fi
+ fi
+ 
+ AC_ARG_WITH(scilab-toolbox-dir,
+             [AS_HELP_STRING([--with-scilab-toolbox-dir],[directory in which the scilab interface will be installed])],
+             SCILAB_TOOLBOX_DIR="$withval",SCILAB_TOOLBOX_DIR="$GFPREFIX/getfem_toolbox")
+ AC_SUBST(SCILAB_TOOLBOX_DIR)
+ 
+ 
+ 
+ dnl -----------------------------------------------
+ dnl Outputs
+ dnl -----------------------------------------------
+ 
+ IM_METHODS=`$srcdir/bin/extract_doc $srcdir/interface/src cubature`
+ IM_METHODS_LOC=`$srcdir/bin/extract_doc $srcdir/interface/src cubature_loc`
+ AC_SUBST(IM_METHODS)
+ AC_SUBST(IM_METHODS_LOC)
+ 
+ 
+ AC_CONFIG_FILES(\
+ 	Makefile\
+ 	m4/Makefile\
+ 	cubature/Makefile\
+ 	$SUPERLU_MAKEFILE\
+ 	doc/Makefile\
+ 	doc/sphinx/Makefile\
+ 	src/Makefile\
+ 	tests/Makefile\
+ 	tests-2.0/Makefile\
+ 	contrib/Makefile\
+ 	contrib/icare/Makefile\
+ 	contrib/delaminated_crack/Makefile\
+ 	contrib/static_friction/Makefile\
+ 	contrib/bimaterial_crack_test/Makefile\
+ 	contrib/bimat_contact_crack_test/Makefile\
+ 	contrib/xfem_stab_unilat_contact/Makefile\
+ 	contrib/mixed_elastostatic/Makefile\
+ 	contrib/contact_grd_trans/Makefile\
+ 	contrib/mixed_dynamic_friction/Makefile\
+ 	contrib/xfem_large_strain/Makefile\
+ 	contrib/xfem_contact/Makefile\
+ 	contrib/crack_plate/Makefile\
+ 	contrib/inter_element_test/Makefile\
+ 	contrib/aposteriori/Makefile\
+ 	contrib/level_set_contact/Makefile\
+ 	contrib/static_contact_gears/Makefile\
+ 	bin/Makefile\
+ 	interface/Makefile\
+ 	interface/src/Makefile\
+ 	interface/src/matlab/Makefile\
+ 	interface/src/matlab/private/Makefile\
+ 	interface/src/python/Makefile\
+ 	interface/src/python/setup.py\
+ 	interface/src/scilab/Makefile\
+ 	interface/src/scilab/sci_gateway/c/builder_gateway_c.sce\
+ 	interface/tests/Makefile\
+ 	interface/tests/meshes/Makefile\
+ 	interface/tests/matlab/Makefile\
+ 	interface/tests/matlab/private/Makefile\
+ 	interface/tests/python/Makefile\
+ 	getfem-config\
+ 	getfem-config-notinstalled\
+ 	gmm-config)
+ AC_OUTPUT
+ chmod a+x getfem-config-notinstalled
+ chmod a+x getfem-config
+ chmod a+x gmm-config
+ 
+ dnl -----------------------------------------------
+ dnl Symbolic links for the meshes in tests/meshes
+ dnl -----------------------------------------------
+ 
+ if test -z ""`echo $srcdir | grep "^/"`; then
+   addpathm="../"
+ else
+   addpathm=""
+ fi
+ 
+ if test ! -d tests/meshes; then
+   ln -s $addpathm$srcdir/tests/meshes tests/meshes
+ fi;
+ 
+ 
+ dnl configuration sum-up
+ 
+ echo
+ echo "------------------------------------------------------------------------------"
+ echo
+ echo "Libraries Used:"
+ echo "---------------"
+ echo
+ 
+ 
+ 
+ if test "x$useQDlib" = "xyes" ; then  
+   echo "- QD library found. High precision (${QD_PREC}-double precision) polynomials"
+   echo "  and integration methods are enabled.";
+ else
++<<<<<<< HEAD:configure.in
++  echo "- QD library not found (not recommended)."
++=======
+   echo "- QD library not found (don't worry, this library is only recommended for very specific uses)."
++>>>>>>> upstream:configure.ac
+ fi;
+ 
+ if test "x$useQHULL" = "xyes"; then
+   echo "- Qhull found. Using the Qhull library for delaunay triangulations."
+ else
+   echo "- Qhull not found. Mesh generation will be disabled."
+ fi;
+ 
+ if test "x$usemuparser" = "xyes"; then
+   echo "- MuParser found. Used for parsing mathematical expressions."
+ else
+   echo "- MuParser not found. Parsing mathematical expressions will be disabled."
+ fi;
+ 
+ if test "x$usemumps" = "xyes"; then
+   echo "- Mumps found. A direct solver for large sparse linear systems."
+ else
+   echo "- Mumps not found. Not using the MUMPS library for large sparse linear systems."
+ fi;
+ 
+ if test x"$acx_lapack_ok" = xyes; then
+   echo "- Lapack library found: $LAPACK_LIBS"
+ else
+   echo "- Lapack library not found: generic (less effective) algorithms will be used"
+ fi
+ 
+ if test "x$HAVE_VENDOR_BLAS" = "x0"; then
+   echo "- *** No usable blas library was found ***"
+   echo "  A generic BLAS implementation will be used, however you should "
+   echo "  consider installing a faster BLAS, such as ATLAS"
+ else
+   echo "- BLAS library found. Link options: $BLAS_LIBS"
+ fi;
+ echo "  You can give the location of your prefered blas library with either"
+ echo "  the --with-blas=<lib> option, or the BLAS_LIBS environment variable"
+ echo '  for example: ./configure BLAS_LIBS="-L/usr/lib/sse2/atlas/ -lblas"'
+ echo
+ echo
+ 
+ 
+ echo "-----------------------------------------------------------------------"
+ echo "Ready to build getfem"
+ echo "  building MATLAB interface: $usematlab"
+ echo "  building PYTHON interface: $usepython (requires numpy and scipy)"
+ echo "  building SCILAB interface: $usescilab"
+ echo "  If you want to build the shared library of getfem++, use --enable-shared"
+ echo "  (by default, only the static one will be built)"
+ echo "-----------------------------------------------------------------------"
+ 
+ case $host in
+   x86_64-*)
+ 	if test $usematlab = "YES" -o $usepython = "YES"; then
+           if test $pic_mode != "yes"; then
+             echo "!!!!!"
+             echo "!!!!! Your build will fail because you did not use the --with-pic option"
+             echo "!!!!! This is required for the getfem interfaces on x86_64"
+             echo ""
+           fi
+         fi      
+   ;;
+ esac
+ 
++<<<<<<< HEAD:configure.in
++echo $shared_mode
++=======
+ echo $shared_mode
++>>>>>>> upstream:configure.ac
diff --cc contrib/icare/Makefile.am
index 9eb019c,e40ae35..cee5725
--- a/contrib/icare/Makefile.am
+++ b/contrib/icare/Makefile.am
@@@ -10,10 -10,10 +10,14 @@@ icare_SOURCES = icare.cc icare.
  SUPLDFLAGS = @SUPLDFLAGS@
  MUMPS_LIBS = @MUMPS_LIBS@
  # MUMPS_CFLAGS = @MUMPS_CFLAGS@
++<<<<<<< HEAD
 +INCLUDES = -I$(top_srcdir)/src -I../../src # $(MUMPS_CFLAGS)
++=======
+ AM_CPPFLAGS = -I$(top_srcdir)/src -I../../src # $(MUMPS_CFLAGS)
++>>>>>>> upstream
  LDADD    = ../../src/libgetfem.la -lm $(MUMPS_LIBS) $(SUPLDFLAGS)
  
- TESTS = $(top_srcdir)/contrib/icare/icare.pl
+ TESTS = $(abs_top_srcdir)/contrib/icare/icare.pl
  
  EXTRA_DIST = \
  	icare.pl                  \
diff --cc contrib/static_contact_gears/static_contact_gears.cc
index e301216,5d36def..8cb2e27
--- a/contrib/static_contact_gears/static_contact_gears.cc
+++ b/contrib/static_contact_gears/static_contact_gears.cc
@@@ -219,20 -253,39 +253,51 @@@ bool elastostatic_contact_problem::solv
  //  getfem::mdbrick_nonlinear_elasticity<>  ELAS(pl, mim, mf_u, p);
    
    // Defining the contact condition.
-   std::string varname_u="u";
-   std::string dataname_r="r";
    md.add_initialized_scalar_data
-     (dataname_r, mu * (3*lambda + 2*mu) / (lambda + mu) );  // r ~= Young modulus
+     ("r", mu * (3*lambda + 2*mu) / (lambda + mu) );  // r ~= Young modulus
    std::string multname_n, multname_t;
++<<<<<<< HEAD
 +  if (frictionless) {
 +    getfem::add_nodal_contact_between_nonmatching_meshes_brick
 +      (md, mim, varname_u, multname_n, dataname_r, cb_rgs1, cb_rgs2);
 +  } else {
 +    std::string dataname_frict_coeff="friction_coefficient";
 +    md.add_initialized_scalar_data(dataname_frict_coeff, frict_coeff);
 +    getfem::add_nodal_contact_between_nonmatching_meshes_brick
 +      (md, mim, mim, varname_u, varname_u, multname_n, multname_t,
 +       dataname_r, dataname_frict_coeff, cb_rgs1, cb_rgs2);
++=======
+   if (contact_algo == 0) {
+     if (frictionless) {
+       getfem::add_nodal_contact_between_nonmatching_meshes_brick
+         (md, mim, "u", multname_n, "r", cb_rgs1, cb_rgs2);
+     } else {
+       std::string dataname_frict_coeff="friction_coefficient";
+       md.add_initialized_scalar_data(dataname_frict_coeff, frict_coeff);
+       getfem::add_nodal_contact_between_nonmatching_meshes_brick
+         (md, mim, "u", multname_n, multname_t,
+          "r", dataname_frict_coeff, cb_rgs1, cb_rgs2);
+     }
+   } else {
+     md.add_fem_variable("mult", mf_mult);
+     if (contact_algo >= 1 && contact_algo <= 4) { // integral contact
+       if (frictionless)
+         getfem::add_integral_contact_between_nonmatching_meshes_brick
+           (md, mim, "u", "u", "mult", "r",
+            CONTACT_BOUNDARY_1, CONTACT_BOUNDARY_2, contact_algo);
+       else {
+         md.add_initialized_scalar_data("f_coeff", frict_coeff);
+         getfem::add_integral_contact_between_nonmatching_meshes_brick
+           (md, mim, "u", "u", "mult", "r", "f_coeff",
+            CONTACT_BOUNDARY_1, CONTACT_BOUNDARY_2, contact_algo);
+       }
+     }
+     else { // large sliding is for the moment always frictionless
+       md.add_initialized_scalar_data("f_coeff", frict_coeff);
+       size_type indb = getfem::add_integral_large_sliding_contact_brick_field_extension
+         (md, mim, "u", "mult", "r", "f_coeff", CONTACT_BOUNDARY);
+     }
++>>>>>>> upstream
    }
  
    // Defining the DIRICHLET condition.
@@@ -258,7 -311,7 +323,11 @@@
    gmm::iteration iter(residual, 1, 40000);
  
    getfem::default_newton_line_search ls;
++<<<<<<< HEAD
 +  getfem::standard_solve(md, iter, getfem::rselect_linear_solver(md,"superlu"), ls);
++=======
+   getfem::standard_solve(md, iter, getfem::rselect_linear_solver(md,"mumps"), ls);
++>>>>>>> upstream
  
    if (!iter.converged()) return false; // Solution has not converged
  
diff --cc contrib/static_contact_gears/static_contact_gears_u1_u2.cc
index 99aad9c,11309f2..37ed213
--- a/contrib/static_contact_gears/static_contact_gears_u1_u2.cc
+++ b/contrib/static_contact_gears/static_contact_gears_u1_u2.cc
@@@ -28,7 -30,6 +30,10 @@@
  using std::endl; using std::cout; using std::cerr;
  using std::ends; using std::cin;
  
++<<<<<<< HEAD
 +
++=======
++>>>>>>> upstream
  /* some Getfem++ types that we will be using */
  using bgeot::dim_type;
  using bgeot::size_type;   /* = unsigned long */
@@@ -230,22 -266,43 +270,56 @@@ bool elastostatic_contact_problem::solv
  //  getfem::mdbrick_nonlinear_elasticity<>  ELAS(pl, mim, mf_u, p);
    
    // Defining the contact condition.
-   std::string varname_u1="u1";
-   std::string varname_u2="u2";
-   std::string dataname_r="r";
    md.add_initialized_scalar_data
-     (dataname_r, mu * (3*lambda + 2*mu) / (lambda + mu) );  // r ~= Young modulus
+     ("r", mu * (3*lambda + 2*mu) / (lambda + mu) );  // r ~= Young modulus
    std::string multname_n, multname_t;
++<<<<<<< HEAD
 +  if (frictionless) {
 +    getfem::add_nodal_contact_between_nonmatching_meshes_brick
 +      (md, mim1, mim2, varname_u1, varname_u2, multname_n, dataname_r,
 +       cb_rgs1, cb_rgs2);
 +  } else {
 +    std::string dataname_frict_coeff="friction_coefficient";
 +    md.add_initialized_scalar_data(dataname_frict_coeff, frict_coeff);
 +    getfem::add_nodal_contact_between_nonmatching_meshes_brick
 +      (md, mim1, mim2, varname_u1, varname_u2, multname_n, multname_t,
 +       dataname_r, dataname_frict_coeff, cb_rgs1, cb_rgs2);
++=======
+   if (contact_algo == 0) {
+     if (frictionless) {
+       getfem::add_nodal_contact_between_nonmatching_meshes_brick
+         (md, mim1, mim2, "u1", "u2", multname_n, "r",
+          cb_rgs1, cb_rgs2);
+     } else {
+       std::string dataname_frict_coeff="friction_coefficient";
+       md.add_initialized_scalar_data(dataname_frict_coeff, frict_coeff);
+       getfem::add_nodal_contact_between_nonmatching_meshes_brick
+         (md, mim1, mim2, "u1", "u2", multname_n, multname_t,
+          "r", dataname_frict_coeff, cb_rgs1, cb_rgs2);
+     }
+   } else {
+     md.add_fem_variable("mult1", mf_mult1);
+     if (contact_algo >= 1 && contact_algo <= 4) { // integral contact
+       if (frictionless)
+         getfem::add_integral_contact_between_nonmatching_meshes_brick
+           (md, mim1, "u1", "u2", "mult1", "r",
+            CONTACT_BOUNDARY_1, CONTACT_BOUNDARY_2, contact_algo);
+       else {
+         md.add_initialized_scalar_data("f_coeff", frict_coeff);
+         getfem::add_integral_contact_between_nonmatching_meshes_brick
+           (md, mim1, "u1", "u2", "mult1", "r", "f_coeff",
+            CONTACT_BOUNDARY_1, CONTACT_BOUNDARY_2, contact_algo);
+       }
+     }
+     else { // large sliding is for the moment always frictionless
+       md.add_fem_variable("mult2", mf_mult2);
+       md.add_initialized_scalar_data("f_coeff", frict_coeff);
+       size_type indb = getfem::add_integral_large_sliding_contact_brick_field_extension
+         (md, mim1, "u1", "mult1", "r", "f_coeff", CONTACT_BOUNDARY_1);
+       getfem::add_boundary_to_large_sliding_contact_brick
+         (md, indb, mim2, "u2", "mult2", CONTACT_BOUNDARY_2);
+     }
++>>>>>>> upstream
    }
  
    // Defining the DIRICHLET condition.
@@@ -272,7 -329,7 +346,11 @@@
    gmm::iteration iter(residual, 1, 40000);
  
    getfem::default_newton_line_search ls;
++<<<<<<< HEAD
 +  getfem::standard_solve(md, iter, getfem::rselect_linear_solver(md,"superlu"), ls);
++=======
+   getfem::standard_solve(md, iter, getfem::rselect_linear_solver(md,"mumps"), ls);
++>>>>>>> upstream
  
    if (!iter.converged()) return false; // Solution has not converged
  
diff --cc contrib/xfem_contact/xfem_stokes.cc
index 7afe5b9,baf0acd..977192d
--- a/contrib/xfem_contact/xfem_stokes.cc
+++ b/contrib/xfem_contact/xfem_stokes.cc
@@@ -191,7 -191,7 +191,11 @@@ public
    level_set_unit_normal(const getfem::mesh_fem &mf_, const VECT1 &U_) 
      : mf(mf_), U(U_), N(mf_.linked_mesh().dim()), gradU(1, N)
    { sizes_.resize(1); sizes_[0] = short_type(N); }
++<<<<<<< HEAD
 +  const bgeot::multi_index &sizes() const {  return sizes_; }
++=======
+   const bgeot::multi_index &sizes(size_type) const {  return sizes_; }
++>>>>>>> upstream
    virtual void compute(getfem::fem_interpolation_context& ctx,
  		       bgeot::base_tensor &t) {
      size_type cv = ctx.convex_num();
diff --cc contrib/xfem_large_strain/compressible_getfem_nonlinear_elastoptim.h
index 03b2fa2,212d4f1..09e736e
--- a/contrib/xfem_large_strain/compressible_getfem_nonlinear_elastoptim.h
+++ b/contrib/xfem_large_strain/compressible_getfem_nonlinear_elastoptim.h
@@@ -107,7 -107,7 +107,11 @@@ namespace getfem 
        if (gmm::vect_size(PARAMS) == AHL_.nb_params())
  	gmm::copy(PARAMS, params);
      }
++<<<<<<< HEAD
 +    const bgeot::multi_index &sizes() const { return sizes_; }
++=======
+     const bgeot::multi_index &sizes(size_type) const { return sizes_; }
++>>>>>>> upstream
      virtual void compute(getfem::fem_interpolation_context& ctx,
  			 bgeot::base_tensor &t) {
        size_type cv = ctx.convex_num();
@@@ -261,7 -261,7 +265,11 @@@
        if (gmm::vect_size(PARAMS) == AHL_.nb_params())
  	gmm::copy(PARAMS, params);
      }
++<<<<<<< HEAD
 +    const bgeot::multi_index &sizes() const {  return sizes_; }
++=======
+     const bgeot::multi_index &sizes(size_type) const {  return sizes_; }
++>>>>>>> upstream
      virtual void compute(getfem::fem_interpolation_context& ctx,
  			 bgeot::base_tensor &t) {
        size_type cv = ctx.convex_num();
@@@ -404,7 -404,7 +412,11 @@@
        if (gmm::vect_size(PARAMS) == AHL_.nb_params())
  	gmm::copy(PARAMS, params);
      }
++<<<<<<< HEAD
 +    const bgeot::multi_index &sizes() const {  return sizes_; }
++=======
+     const bgeot::multi_index &sizes(size_type) const {  return sizes_; }
++>>>>>>> upstream
      virtual void compute(getfem::fem_interpolation_context& ctx,
  			 bgeot::base_tensor &t) {
        size_type cv = ctx.convex_num();
@@@ -507,7 -507,7 +519,11 @@@
        if (gmm::vect_size(PARAMS) == AHL_.nb_params())
  	gmm::copy(PARAMS, params);
      }
++<<<<<<< HEAD
 +    const bgeot::multi_index &sizes() const {  return sizes_; }
++=======
+     const bgeot::multi_index &sizes(size_type) const {  return sizes_; }
++>>>>>>> upstream
      virtual void compute(getfem::fem_interpolation_context& ctx,
  			 bgeot::base_tensor &t) {
        size_type cv = ctx.convex_num();
@@@ -602,7 -602,7 +618,11 @@@
        if (gmm::vect_size(PARAMS) == AHL_.nb_params())
  	gmm::copy(PARAMS, params);
      }
++<<<<<<< HEAD
 +    const bgeot::multi_index &sizes() const {  return sizes_; }
++=======
+     const bgeot::multi_index &sizes(size_type) const {  return sizes_; }
++>>>>>>> upstream
      virtual void compute(getfem::fem_interpolation_context& ctx,
  			 bgeot::base_tensor &t) {
        size_type cv = ctx.convex_num();
diff --cc contrib/xfem_stab_unilat_contact/xfem_stab_unilat_contact.cc
index f1319c3,7d113f9..0bc3405
--- a/contrib/xfem_stab_unilat_contact/xfem_stab_unilat_contact.cc
+++ b/contrib/xfem_stab_unilat_contact/xfem_stab_unilat_contact.cc
@@@ -42,6 -42,8 +42,11 @@@
  #include "getfem/getfem_mesh_fem_sum.h"
  #include "gmm/gmm_inoutput.h"
  
++<<<<<<< HEAD
++=======
+ #ifdef GETFEM_HAVE_METIS
+ 
++>>>>>>> upstream
  extern "C" void METIS_PartGraphKway(int *, int *, int *, int *, int *, int *,
  			    int *, int *, int *, int *, int *);
  extern "C" void METIS_PartGraphRecursive(int *, int *, int *, int *, int *, int *,
@@@ -52,6 -54,10 +57,13 @@@ extern "C" void METIS_mCPartGraphKway(i
  				      int *, int *, float *, int *, int *, int *);
  extern "C" void METIS_mCPartGraphRecursive(int *, int *, int *, int *, int *, int *, int *,
  				      int *, int *, int *, int *, int *);
++<<<<<<< HEAD
++=======
+ 
+ #endif
+ 
+ using std::endl; using std::cout; using std::cerr;
++>>>>>>> upstream
  
  /* some Getfem++ types that we will be using */
  using bgeot::base_small_vector; /* special class for small (dim<16) vectors */
@@@ -500,6 -506,9 +512,12 @@@ void asm_stabilization_patch_ter
    int wgtflag = 2, edgecut, nparts=int(size_of_crack/(ratio_size*h)), numflag = 0;
        // float ubvec[1] = {1.03f};
    int  options[5] = {0,0,0,0,0};
++<<<<<<< HEAD
++=======
+ 
+ #ifdef GETFEM_HAVE_METIS
+ 
++>>>>>>> upstream
    //METIS_mCPartGraphKway(&ne, &ncon, &(xadj[0]), &(adjncy[0]), &(vwgt[0]), &(adjwgt[0]), &wgtflag,
    //		    &numflag, &nparts, &(ubvec[0]),  options, &edgecut, &(part[0]));
    // METIS_mCPartGraphRecursive(&ne, &ncon, &(xadj[0]), &(adjncy[0]), &(vwgt[0]), &(adjwgt[0]), &wgtflag,
@@@ -509,6 -518,12 +527,15 @@@
    METIS_PartGraphRecursive(&ne, &(xadj[0]), &(adjncy[0]), &(vwgt[0]), &(adjwgt[0]), &wgtflag,
  			   &numflag, &nparts, options, &edgecut, &(part[0]));
    
++<<<<<<< HEAD
++=======
+ #else
+ 
+   GMM_ASSERT1(false, "METIS not linked");
+ 
+ #endif
+ 
++>>>>>>> upstream
    //cout<<"size_of_mesh="<<h<<endl;
    cout<<"size_of_crack="<< size_of_crack <<endl;
    cout<<"nb_partition="<<nparts<<endl;
@@@ -1289,11 -1304,11 +1316,19 @@@ bool  unilateral_contact_problem::solve
  						  "augmentation_parameter", BN, MA);
      }else{
        if (Tresca_version){
++<<<<<<< HEAD
 +	getfem::add_Hughes_stab_with_friction_contact_brick
 +	  (model, "u", "Lambda", "Lambda_t", "augmentation_parameter",
 +	   BN, BT, MA, MAT, "Friction_coeff","","",1, Tresca_version, "Tresca_threshold");
 +      }else{
 +	getfem::add_Hughes_stab_with_friction_contact_brick
++=======
+ 	getfem::add_Hughes_stab_basic_contact_brick
+ 	  (model, "u", "Lambda", "Lambda_t", "augmentation_parameter",
+ 	   BN, BT, MA, MAT, "Friction_coeff","","",1, Tresca_version, "Tresca_threshold");
+       }else{
+ 	getfem::add_Hughes_stab_basic_contact_brick
++>>>>>>> upstream
  	  (model, "u", "Lambda", "Lambda_t", "augmentation_parameter",
  	   BN, BT, MA, MAT, "Friction_coeff");
        }
@@@ -1305,11 -1320,11 +1340,19 @@@
  				      "augmentation_parameter", BN);
      }else{
        if (Tresca_version){
++<<<<<<< HEAD
 +     	getfem::add_basic_contact_with_friction_brick
 +	  (model, "u", "Lambda", "Lambda_t",
 +	   "augmentation_parameter", BN, BT, "Friction_coeff","","",1,Tresca_version,"Tresca_threshold");
 +      }else{
 +	getfem::add_basic_contact_with_friction_brick
++=======
+      	getfem::add_basic_contact_brick
+ 	  (model, "u", "Lambda", "Lambda_t",
+ 	   "augmentation_parameter", BN, BT, "Friction_coeff","","",1,Tresca_version,"Tresca_threshold");
+       }else{
+ 	getfem::add_basic_contact_brick
++>>>>>>> upstream
  	  (model, "u", "Lambda", "Lambda_t",
  	   "augmentation_parameter", BN, BT, "Friction_coeff");
        }
@@@ -1333,7 -1348,7 +1376,11 @@@
  //       getfem::add_explicit_matrix(model, "u", "u", KAT);
  //       // Defining the contact condition.
  //       gmm::add(CAT, BT); 
++<<<<<<< HEAD
 +//       getfem::add_Hughes_stab_with_friction_contact_brick
++=======
+ //       getfem::add_Hughes_stab_basic_contact_brick
++>>>>>>> upstream
  // 	(model, "u", "Lambda", "Lambda_t", "augmentation_parameter",
  // 	 BN, BT, MA, MAT, "friction_coeff");
  //     }
@@@ -1342,7 -1357,7 +1389,11 @@@
  // 				    "augmentation_parameter", BN);
      
  //     if (!contact_only){
++<<<<<<< HEAD
 +//       getfem::add_basic_contact_with_friction_brick
++=======
+ //       getfem::add_basic_contact_brick
++>>>>>>> upstream
  // 	(model, "u", "Lambda", "Lambda_t",
  // 	 "augmentation_parameter", BN, BT, "friction_coeff","","",0);
        
diff --cc doc/sphinx/Makefile.am
index 455cfd8,a9225db..eb81d0d
--- a/doc/sphinx/Makefile.am
+++ b/doc/sphinx/Makefile.am
@@@ -146,7 -147,6 +147,10 @@@ upload
  	(export srcdir=$(srcdir) && $(top_srcdir)/bin/upload_documentation --delete getfem_project.pdf)
  	(export srcdir=$(srcdir) && $(top_srcdir)/bin/upload_documentation --delete gmm_userdoc.pdf)
  	rm -fr *.pdf
++<<<<<<< HEAD
 +	rm -fr build
++=======
++>>>>>>> upstream
  
  
  EXTRA_DIST = \
diff --cc doc/sphinx/source/userdoc/images/Makefile
index ed32b36,4dce583..cc0aa27
--- a/doc/sphinx/source/userdoc/images/Makefile
+++ b/doc/sphinx/source/userdoc/images/Makefile
@@@ -72,7 -72,11 +72,15 @@@ FIGS=getfemlistargyris.fi
       getfemuserelem.fig                      \
       getfemuserlinearsys.fig                 \
       getfemuserlinsysDir.fig                 \
++<<<<<<< HEAD
 +     getfemuserrefine.fig
++=======
+      getfemuserrefine.fig		     \
+      getfemusermodelmasterslave.fig          \
+      getfemusermodeldetectcontact.fig        \
+      getfemusermodelfalsecontact1.fig        \
+      getfemusermodelfalsecontact2.fig
++>>>>>>> upstream
  
  EPSFIGS=$(FIGS:.fig=.eps)
  PNGFIGS=$(FIGS:.fig=.png)
@@@ -83,7 -87,7 +91,11 @@@
  	../../../../../bin/fig2eps $(@:.eps=.fig)
  
  .eps.png:
++<<<<<<< HEAD
 +	convert $(@:.png=.eps) $@
++=======
+ 	convert -density 100 $(@:.png=.eps) $@
++>>>>>>> upstream
  
  png: $(PNGFIGS)
  
diff --cc interface/src/Makefile.am
index 6ea22fb,af086d3..15d684b
--- a/interface/src/Makefile.am
+++ b/interface/src/Makefile.am
@@@ -23,6 -23,9 +23,12 @@@ PSEUDO_MFUNCTIONS = 
  	gf_util.cc \
  	gf_cont_struct.cc \
  	gf_cont_struct_get.cc \
++<<<<<<< HEAD
++=======
+ 	gf_multi_contact_frame.cc \
+ 	gf_multi_contact_frame_get.cc \
+ 	gf_multi_contact_frame_set.cc \
++>>>>>>> upstream
  	gf_cvstruct_get.cc \
  	gf_geotrans.cc \
  	gf_geotrans_get.cc \
@@@ -96,6 -99,7 +102,10 @@@ libgetfemint_la_SOURCES = 
  	getfemint_convex_structure.cc \
  	gfi_array.h \
  	getfemint_cont_struct.h \
++<<<<<<< HEAD
++=======
+ 	getfemint_multi_contact_frame.h \
++>>>>>>> upstream
  	getfemint_convex_structure.h \
  	getfemint_mesh.h \
  	getfemint_mesher_object.h \
diff --cc interface/src/getfem_interface.cc
index 46049a9,225959d..acaee51
--- a/interface/src/getfem_interface.cc
+++ b/interface/src/getfem_interface.cc
@@@ -18,7 -18,7 +18,11 @@@
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
   
  ===========================================================================*/
++<<<<<<< HEAD
 +// $Id: getfem_interface.cc 4114 2012-07-06 11:20:10Z renard $
++=======
+ // $Id: getfem_interface.cc 4285 2013-04-19 09:45:24Z renard $
++>>>>>>> upstream
  #include <getfem_interface.h>
  #include <getfemint.h>
  
@@@ -38,6 -38,9 +42,12 @@@ void gf_fem(getfemint::mexargs_in& in, 
  void gf_fem_get(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
  void gf_cont_struct(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
  void gf_cont_struct_get(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
++<<<<<<< HEAD
++=======
+ void gf_multi_contact_frame(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
+ void gf_multi_contact_frame_get(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
+ void gf_multi_contact_frame_set(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
++>>>>>>> upstream
  void gf_cvstruct_get(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
  void gf_mesh(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
  void gf_mesher_object(getfemint::mexargs_in& in, getfemint::mexargs_out& out);
@@@ -140,6 -143,9 +150,12 @@@ char* getfem_interface_main(int config_
      subc_tab["global_function_get"] = gf_global_function_get;
      subc_tab["cont_struct"] = gf_cont_struct;
      subc_tab["cont_struct_get"] = gf_cont_struct_get;
++<<<<<<< HEAD
++=======
+     subc_tab["multi_contact_frame"] = gf_multi_contact_frame;
+     subc_tab["multi_contact_frame_get"] = gf_multi_contact_frame_get;
+     subc_tab["multi_contact_frame_set"] = gf_multi_contact_frame_set;
++>>>>>>> upstream
      subc_tab["fem"] = gf_fem;
      subc_tab["fem_get"] = gf_fem_get;
      subc_tab["cvstruct_get"] = gf_cvstruct_get;
diff --cc interface/src/getfemint.cc
index 1904a7a,980e7b5..7d63f11
--- a/interface/src/getfemint.cc
+++ b/interface/src/getfemint.cc
@@@ -44,6 -44,7 +44,10 @@@
  #include <getfemint_global_function.h>
  #include <getfemint_mesher_object.h>
  #include <getfemint_cont_struct.h>
++<<<<<<< HEAD
++=======
+ #include <getfemint_multi_contact_frame.h>
++>>>>>>> upstream
  #include <getfem/getfem_mat_elem_type.h>
  #include <getfem/getfem_mesh_fem_global_function.h>
  #include <getfem/getfem_mesher.h>
@@@ -421,6 -423,15 +426,18 @@@ namespace getfemint 
    }
  
    bool
++<<<<<<< HEAD
++=======
+   mexarg_in::is_multi_contact_frame() {
+     id_type id, cid;
+     if (is_object_id(&id, &cid) && cid == MULTI_CONTACT_FRAME_CLASS_ID) {
+       getfem_object *o=workspace().object(id, name_of_getfemint_class_id(cid));
+       return (object_is_multi_contact_frame(o));
+     } else return false;
+   }
+ 
+   bool
++>>>>>>> upstream
    mexarg_in::is_gsparse() {
      id_type id, cid;
      if (is_object_id(&id, &cid) && cid == GSPARSE_CLASS_ID) {
@@@ -772,6 -783,33 +789,36 @@@
      return &to_getfemint_cont_struct(true)->cont_struct();
    }
  
++<<<<<<< HEAD
++=======
+   /*
+     check if the argument is a valid handle to a multi_contact_frame object,
+     and return it
+   */
+   getfemint_multi_contact_frame *
+   mexarg_in::to_getfemint_multi_contact_frame(bool writeable) {
+     id_type id, cid;
+     to_object_id(&id,&cid);
+     if (cid != MULTI_CONTACT_FRAME_CLASS_ID) {
+       THROW_BADARG("argument " << argnum << " should be a multi_contact_frame "
+                    << "descriptor, its class is "
+                    << name_of_getfemint_class_id(cid));
+     }
+     getfem_object *o = workspace().object(id, name_of_getfemint_class_id(cid));
+     error_if_nonwritable(o, writeable);
+     return object_to_multi_contact_frame(o);
+   }
+ 
+   const getfem::multi_contact_frame *
+   mexarg_in::to_const_multi_contact_frame() {
+     return &to_getfemint_multi_contact_frame(false)->multi_contact_frame();
+   }
+ 
+   getfem::multi_contact_frame *
+   mexarg_in::to_multi_contact_frame() {
+     return &to_getfemint_multi_contact_frame(true)->multi_contact_frame();
+   }
++>>>>>>> upstream
  
    getfemint_precond *
    mexarg_in::to_precond() {
diff --cc interface/src/getfemint.h
index 1c1b350,e583410..9d142ef
--- a/interface/src/getfemint.h
+++ b/interface/src/getfemint.h
@@@ -53,6 -53,7 +53,10 @@@ namespace getfem 
    class abstract_xy_function;
    class mesher_signed_distance;
    class cont_struct_getfem_model;
++<<<<<<< HEAD
++=======
+   class multi_contact_frame;
++>>>>>>> upstream
  }
  
  namespace getfemint
@@@ -101,6 -102,7 +105,10 @@@
    class getfemint_global_function;
    class getfemint_mesher_object;
    class getfemint_cont_struct;
++<<<<<<< HEAD
++=======
+   class getfemint_multi_contact_frame;
++>>>>>>> upstream
    class gsparse;
  
    class sub_index : public gmm::unsorted_sub_index{
@@@ -403,6 -405,7 +411,10 @@@ namespace getfemint 
      bool                                 is_global_function();
      bool                                 is_mesher_object();
      bool                                 is_cont_struct();
++<<<<<<< HEAD
++=======
+     bool                                 is_multi_contact_frame();
++>>>>>>> upstream
      bool                                 is_sparse() { return (gfi_array_get_class(arg) == GFI_SPARSE || is_gsparse()); };
      bool                                 is_gsparse();
      bool                                 is_complex(); /* true for complex garrays AND complex sparse matrices (native or gsparse) */
@@@ -442,9 -445,12 +454,18 @@@
      getfem::mesher_signed_distance *     to_mesher_object();
      const getfem::cont_struct_getfem_model * to_const_cont_struct();
      getfem::cont_struct_getfem_model *   to_cont_struct();
++<<<<<<< HEAD
 +    getfemint_global_function *          to_getfemint_global_function(bool writeable=false);
 +    getfemint_mesher_object *            to_getfemint_mesher_object(bool writeable=false);
 +    getfemint_cont_struct *              to_getfemint_cont_struct(bool writable=false);
++=======
+     const getfem::multi_contact_frame *  to_const_multi_contact_frame();
+     getfem::multi_contact_frame *        to_multi_contact_frame();
+     getfemint_global_function *          to_getfemint_global_function(bool writeable=false);
+     getfemint_mesher_object *            to_getfemint_mesher_object(bool writeable=false);
+     getfemint_cont_struct *              to_getfemint_cont_struct(bool writable=false);
+     getfemint_multi_contact_frame *      to_getfemint_multi_contact_frame(bool writable=false);
++>>>>>>> upstream
      getfem::pintegration_method          to_integration_method();
      getfemint_pfem*                      to_getfemint_pfem();
      getfem::pfem                         to_fem();
diff --cc interface/src/getfemint_cont_struct.h
index 07a12a1,8e525d1..06d93dc
--- a/interface/src/getfemint_cont_struct.h
+++ b/interface/src/getfemint_cont_struct.h
@@@ -30,7 -30,7 +30,11 @@@
  ===========================================================================*/
  
  /**\file getfemint_cont_struct.h
++<<<<<<< HEAD
 +   \brief interface for the continuation in Getfem models
++=======
+    \brief getfem::cont_struct_getfem_model interface
++>>>>>>> upstream
  */
  
  #include <getfemint_std.h>
@@@ -53,9 -53,12 +57,18 @@@ namespace getfemint 
      id_type class_id() const { return CONT_STRUCT_CLASS_ID; }
      size_type memsize() const {
        size_type szd = sizeof(double);
++<<<<<<< HEAD
 +      return 2* gmm::vect_size(s->b_x()) * szd
 +	+ gmm::vect_size(s->get_tau_hist()) * szd
 +	+ sizeof(getfem::cont_struct_getfem_model);
++=======
+       return sizeof(getfem::cont_struct_getfem_model) 
+ 	+ ((int) s->bifurcations())
+ 	  * (2 * gmm::vect_size(s->b_x()) * szd
+ 	     + 4 * gmm::vect_size(s->get_tau_hist()) * szd
+ 	     + (1 + s->nb_tangent_sing()) * gmm::vect_size(s-> get_x_sing())
+ 	       * szd);
++>>>>>>> upstream
      }
  
      static getfemint_cont_struct*
diff --cc interface/src/getfemint_misc.cc
index 2ee2a4f,856e557..6bf9b0a
--- a/interface/src/getfemint_misc.cc
+++ b/interface/src/getfemint_misc.cc
@@@ -717,7 -739,7 +739,11 @@@ namespace getfemint 
        { if (N == 2) return PS_CG_AHL; else return CG_AHL; }
  
      if (cmd_strmatch(lawname, "generalized Blatz Ko") ||
++<<<<<<< HEAD
 +	cmd_strmatch(lawname, "gbk"))
++=======
+         cmd_strmatch(lawname, "gbk"))
++>>>>>>> upstream
        {	if (N == 2) return PS_GBK_AHL; else return GBK_AHL; }
      
  
diff --cc interface/src/getfemint_workspace.cc
index fdd7664,f0ba121..5a9dc75
--- a/interface/src/getfemint_workspace.cc
+++ b/interface/src/getfemint_workspace.cc
@@@ -1,6 -1,6 +1,10 @@@
  /*===========================================================================
   
++<<<<<<< HEAD
 + Copyright (C) 2006-2012 Yves Renard, Julien Pommier.
++=======
+  Copyright (C) 2002-2013 Julien Pommier.
++>>>>>>> upstream
   
   This file is a part of GETFEM++
   
@@@ -18,7 -18,7 +22,11 @@@
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
   
  ===========================================================================*/
++<<<<<<< HEAD
 +// $Id: getfemint_workspace.cc 4114 2012-07-06 11:20:10Z renard $
++=======
+ // $Id: getfemint_workspace.cc 4309 2013-05-10 07:29:39Z renard $
++>>>>>>> upstream
  #define GETFEMINT_WORKSPACE_C
  
  #include <getfem/dal_singleton.h>
diff --cc interface/src/getfemint_workspace.h
index 7566df9,298de33..c0f594b
--- a/interface/src/getfemint_workspace.h
+++ b/interface/src/getfemint_workspace.h
@@@ -1,7 -1,7 +1,11 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
   
++<<<<<<< HEAD
 + Copyright (C) 2002-2012 Julien Pommier
++=======
+  Copyright (C) 2002-2013 Julien Pommier
++>>>>>>> upstream
   
   This file is a part of GETFEM++
   
@@@ -28,7 -28,7 +32,11 @@@
   might be covered by the GNU Lesser General Public License.
   
  ===========================================================================*/
++<<<<<<< HEAD
 +// $Id: getfemint_workspace.h 4114 2012-07-06 11:20:10Z renard $
++=======
+ // $Id: getfemint_workspace.h 4309 2013-05-10 07:29:39Z renard $
++>>>>>>> upstream
  #ifndef GETFEMINT_WORKSPACE_H__
  #define GETFEMINT_WORKSPACE_H__
  
diff --cc interface/src/gf_asm.cc
index bd4f034,2c9d56a..f575a79
--- a/interface/src/gf_asm.cc
+++ b/interface/src/gf_asm.cc
@@@ -58,7 -59,7 +59,11 @@@ public
      sizes_.resize(1); sizes_[0] = bgeot::short_type(N);
      mf.extend_vector(U_, U);
    }
++<<<<<<< HEAD
 +  const bgeot::multi_index &sizes() const {  return sizes_; }
++=======
+   const bgeot::multi_index &sizes(getfem::size_type) const {  return sizes_; }
++>>>>>>> upstream
    virtual void compute(getfem::fem_interpolation_context& ctx,
  		       bgeot::base_tensor &t) {
      bgeot::size_type cv = ctx.convex_num();
@@@ -615,14 -618,19 +622,30 @@@ void gf_asm(getfemint::mexargs_in& m_in
        may be choosen among:
        
        - 'SaintVenant Kirchhoff':
++<<<<<<< HEAD
 +      Linearized law, should be avoided). This law has the two usual
 +      Lame coefficients as parameters, called lambda and mu.
 +      - 'Mooney Rivlin':
 +      Only for incompressibility. This law has two parameters,
 +      called C1 and C2.
 +      - 'Ciarlet Geymonat':
 +      This law has 3 parameters, called lambda, mu and gamma, with
 +      gamma chosen such that gamma is in ]-lambda/2-mu, -mu[.
++=======
+         Linearized law, should be avoided). This law has the two usual
+         Lame coefficients as parameters, called lambda and mu.
+       - 'Mooney Rivlin':
+         This law has three parameters, called C1, C2 and D1.
+         Can be preceded with the words 'compressible' or 'incompressible' to force
+         a specific version. By default, the incompressible version is considered
+         which requires only the first two material coefficients.
+       - 'neo Hookean':
+         A special case of the 'Mooney Rivlin' law that requires one material
+         coefficient less (C2 = 0). By default, its compressible version is used.
+       - 'Ciarlet Geymonat':
+         This law has 3 parameters, called lambda, mu and gamma, with
+         gamma chosen such that gamma is in ]-lambda/2-mu, -mu[.
++>>>>>>> upstream
        
      The parameters of the material law are described on the @tmf `mf_d`.
      The matrix `params` should have `nbdof(mf_d)` columns, each row
@@@ -1029,7 -1037,6 +1052,10 @@@
         
         );
  
++<<<<<<< HEAD
 +
++=======
++>>>>>>> upstream
    }
  
    if (m_in.narg() < 1)  THROW_BADARG( "Wrong number of input arguments");
diff --cc interface/src/gf_cont_struct.cc
index 0a1d45e,cc497db..7f0e4f3
--- a/interface/src/gf_cont_struct.cc
+++ b/interface/src/gf_cont_struct.cc
@@@ -29,21 -29,21 +29,38 @@@ using namespace getfemint
  
  /*@GFDOC
    This object serves for storing parameters and data used in numerical
++<<<<<<< HEAD
 +  continuation (for more details about the continuation see the Getfem++ user
 +  documentation).
++=======
+   continuation of solution branches of models (for more details about
+   continuation see the Getfem++ user documentation).
++>>>>>>> upstream
  @*/
  
  void gf_cont_struct(getfemint::mexargs_in& in, getfemint::mexargs_out& out) {
    getfemint_cont_struct *pgs = NULL;  
++<<<<<<< HEAD
 +  if (check_cmd("ContStruct", "ContStruct", in, out, 3, 35, 0, 1)) {
 +    
 +    /*@INIT S = ('.init', @tmodel md, @str dataname_parameter[, at str dataname_init, @str dataname_final, @str dataname_current], @scalar sc_fac[, ...])
 +    The variable `dataname_parameter` should parametrise the model given by
 +    `md`. If the parametrisation is done via some vector datum,
 +    `dataname_init` and `dataname_final` should store two given values of
 +    this datum determining the parametrisation, and `dataname_current`
 +    serves for actual values of this datum. `sc_fac` is a scale factor
 +    involved in the norm used in the continuation.
++=======
+   if (check_cmd("ContStruct", "ContStruct", in, out, 3, 43, 0, 1)) {
+     
+     /*@INIT S = ('.init', @tmodel md, @str dataname_parameter[, at str dataname_init, @str dataname_final, @str dataname_current], @scalar sc_fac[, ...])
+     The variable `dataname_parameter` should parametrise the model given by
+     `md`. If the parametrisation is done via a vector datum, `dataname_init`
+     and `dataname_final` should store two given values of this datum
+     determining the parametrisation, and `dataname_current` serves for actual
+     values of this datum. `sc_fac` is a scale factor involved in the weighted
+     norm used in the continuation.
++>>>>>>> upstream
      
      Additional options:
      
@@@ -52,66 -52,83 +69,142 @@@
         (the default value is 'auto', which lets getfem choose itself);
         possible values are 'superlu', 'mumps' (if supported), 'cg/ildlt',
         'gmres/ilu' and 'gmres/ilut';
++<<<<<<< HEAD
 +    - 'max_iter', @int NIT
 +       maximum number of iterations allowed in the correction (the default
 +       value is 10);
 +    - 'thr_iter', @int TIT
 +       threshold number of iterations of the correction for enlarging the
 +       step size (the default value is 8);
 +    - 'max_res', @scalar RES
 +       target residual value of the new point (the default value is 1e-6);
 +    - 'max_diff', @scalar DIFF
 +       determines a convergence criterion to the new tangent vector (the
 +       default value is 1e-9);
 +    - 'min_ang', @scalar ANG
 +       minimal value of the cosine of the angle between tangents to the
 +       solution curve at the old point and the new one (the default value
 +       is 0.9);
 +    - 'h_init', @scalar HIN
 +       initial step size (the default value is 1e-2);
 +    - 'h_max', @scalar HMAX
 +       maximal step size (the default value is 1e-1);
 +    - 'h_min', @scalar HMIN
 +       minimal step size (the default value is 1e-5);
++=======
+     - 'bifurcations'
+        activates tools for detection and treatment of bifurcation points;
+     - 'h_init', @scalar HIN
+        initial step size (the default value is 1e-2);
+     - 'h_max', @scalar HMAX
+        maximum step size (the default value is 1e-1);
+     - 'h_min', @scalar HMIN
+        minimum step size (the default value is 1e-5);
++>>>>>>> upstream
      - 'h_inc', @scalar HINC
         factor for enlarging the step size (the default value is 1.3);
      - 'h_dec', @scalar HDEC
         factor for diminishing the step size (the default value is 0.5);
++<<<<<<< HEAD
 +    - 'epsilon', @scalar EPS
 +       increment to be used to compute the incorporated finite
 +       differences (the default value is 1e-8);
 +    - 'max_res_solve', @scalar RES_SOLVE
 +       target residual value for the linear systems to be solved (the
 +       default value is 1e-7);
 +    - 'nb_test', @int NTEST
 +       number of evaluations of the test function when passing through
 +       a boundary between different smooth pieces;
 +    - 'noisy' or 'very_noisy'
 +       determines how detailed information has to be displayed during the
 +       process (residual values etc.).@*/
 +    
 +       getfemint_model *md = in.pop().to_getfemint_model();
 +
 +       bool with_parametrized_data = false;
 +       std::string dataname_parameter = in.pop().to_string();
 +       std::string dataname_init; std::string dataname_final;
 +       std::string dataname_current;
 +       if (in.front().is_string()) {
 +         with_parametrized_data = true;
++=======
+     - 'max_iter', @int MIT
+        maximum number of iterations allowed in the correction (the default
+        value is 10);
+     - 'thr_iter', @int TIT
+        threshold number of iterations of the correction for enlarging the
+        step size (the default value is 4);
+     - 'max_res', @scalar RES
+        target residual value of a new point on the solution curve (the
+        default value is 1e-6);
+     - 'max_diff', @scalar DIFF
+        determines a convergence criterion for two consecutive points (the
+        default value is 1e-6);
+     - 'min_cos', @scalar MCOS
+        minimal value of the cosine of the angle between tangents to the
+        solution curve at an old point and a new one (the default value is
+        0.9);
+     - 'max_res_solve', @scalar RES_SOLVE
+        target residual value for the linear systems to be solved (the
+        default value is 1e-8);
+     - 'non-smooth'
+        determines that some special methods for non-smooth problems can be
+        used;
+     - 'delta_max', @scalar DMAX
+        maximum size of division for evaluating the test function on the
+        convex combination of two augmented Jacobians that belong to different
+        smooth pieces (the default value is 0.005);
+     - 'delta_min', @scalar DMIN
+        minimum size of division for evaluating the test function on the
+        convex combination (the default value is 0.00012);
+     - 'thr_var', @scalar TVAR
+        threshold variation for refining the division (the default value is
+        0.02);
+     - 'nb_dir', @int NDIR
+        number of linear combinations of vectors in one subspace when
+        searching for new tangent predictions during location of new one-sided
+        branches (the default value is 40);
+     - 'nb_comb', @int NCOMB
+        maximum number of couples of reference vectors forming the linear
+        combinations (the default value is 1);
+     - 'noisy' or 'very_noisy'
+        determines how detailed information has to be displayed during the
+        continuation process (residual values etc.).@*/
+     
+        getfemint_model *md = in.pop().to_getfemint_model();
+        bool bifurcations = false; bool nonsmooth = false;
+        std::string dataname_parameter = in.pop().to_string();
+        bool with_parametrised_data = false;
+        std::string dataname_init; std::string dataname_final;
+        std::string dataname_current;
+        if (in.front().is_string()) {
+          with_parametrised_data = true;
++>>>>>>> upstream
           dataname_init = in.pop().to_string();
           dataname_final = in.pop().to_string();
           dataname_current = in.pop().to_string();
         } 
         scalar_type scfac = in.pop().to_scalar();
  
++<<<<<<< HEAD
 +       std::string lsolver = "auto";
 +       size_type maxit = 10; size_type thrit = 8;
 +       scalar_type maxres = 1.e-6; scalar_type maxdiff = 1.e-9;
 +       scalar_type minang = 0.9; scalar_type h_init = 1.e-2;
 +       scalar_type h_max = 1.e-1; scalar_type h_min = 1.e-5;
 +       scalar_type h_inc = 1.3; scalar_type h_dec = 0.5;
 +       scalar_type epsilon = 1.e-8; scalar_type maxres_solve = 1.e-7;
 +       size_type nb_test = 50;
++=======
+        std::string lsolver = "auto"; scalar_type h_init = 1.e-2;
+        scalar_type h_max = 1.e-1; scalar_type h_min = 1.e-5;
+        scalar_type h_inc = 1.3; scalar_type h_dec = 0.5;
+        size_type maxit = 10; size_type thrit = 4; scalar_type maxres = 1.e-6;
+        scalar_type maxdiff = 1.e-6; scalar_type mincos = 0.9;
+        scalar_type maxres_solve = 1.e-8; scalar_type delta_max = 0.005;
+        scalar_type delta_min = 0.00012;
+        scalar_type thrvar = 0.02; size_type nbdir = 40; size_type nbcomb = 1;
++>>>>>>> upstream
         int noisy = 0;
  
         while (in.remaining() && in.front().is_string()) {
@@@ -119,22 -136,8 +212,27 @@@
           if (cmd_strmatch(opt, "lsolver"))  {
             if (in.remaining()) lsolver = in.pop().to_string();
             else THROW_BADARG("missing name for " << opt);
++<<<<<<< HEAD
 +         } else if (cmd_strmatch(opt, "max_iter")) {
 +           if (in.remaining()) maxit = in.pop().to_integer();
 +           else THROW_BADARG("missing value for " << opt);
 +         } else if (cmd_strmatch(opt, "thr_iter")) {
 +           if (in.remaining()) thrit = in.pop().to_integer();
 +           else THROW_BADARG("missing value for " << opt);
 +         } else if (cmd_strmatch(opt, "max_res")) {
 +           if (in.remaining()) maxres = in.pop().to_scalar();
 +           else THROW_BADARG("missing value for " << opt);
 +         } else if (cmd_strmatch(opt, "max_diff")) {
 +           if (in.remaining()) maxdiff = in.pop().to_scalar();
 +           else THROW_BADARG("missing value for " << opt);
 +         } else if (cmd_strmatch(opt, "min_ang")) {
 +           if (in.remaining()) minang = in.pop().to_scalar();
 +           else THROW_BADARG("missing value for " << opt);
 +         } else if (cmd_strmatch(opt, "h_init")) {
++=======
+          } else if (cmd_strmatch(opt, "bifurcations")) bifurcations = true;
+          else if (cmd_strmatch(opt, "h_init")) {
++>>>>>>> upstream
             if (in.remaining()) h_init = in.pop().to_scalar();
             else THROW_BADARG("missing value for " << opt);
           } else if (cmd_strmatch(opt, "h_max")) {
@@@ -149,42 -152,66 +247,100 @@@
           } else if (cmd_strmatch(opt, "h_dec")) {
             if (in.remaining()) h_dec = in.pop().to_scalar();
             else THROW_BADARG("missing value for " << opt);
++<<<<<<< HEAD
 +         } else if (cmd_strmatch(opt, "epsilon")) {
 +           if (in.remaining()) epsilon = in.pop().to_scalar();
++=======
+          } else if (cmd_strmatch(opt, "max_iter")) {
+            if (in.remaining()) maxit = in.pop().to_integer();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "thr_iter")) {
+            if (in.remaining()) thrit = in.pop().to_integer();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "max_res")) {
+            if (in.remaining()) maxres = in.pop().to_scalar();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "max_diff")) {
+            if (in.remaining()) maxdiff = in.pop().to_scalar();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "min_cos")) {
+            if (in.remaining()) mincos = in.pop().to_scalar();
++>>>>>>> upstream
             else THROW_BADARG("missing value for " << opt);
           } else if (cmd_strmatch(opt, "max_res_solve")) {
             if (in.remaining()) maxres_solve = in.pop().to_scalar();
             else THROW_BADARG("missing value for " << opt);
++<<<<<<< HEAD
 +         } else if (cmd_strmatch(opt, "nb_test")) {
 +           if (in.remaining()) nb_test = in.pop().to_integer();
 +           else THROW_BADARG("missing value for " << opt);
 +         } else if (cmd_strmatch(opt, "noisy")) noisy = 1;
++=======
+          } else if (cmd_strmatch(opt, "delta_max")) {
+            if (in.remaining()) delta_max = in.pop().to_scalar();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "delta_min")) {
+            if (in.remaining()) delta_min = in.pop().to_scalar();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "thr_var")) {
+            if (in.remaining()) thrvar = in.pop().to_scalar();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "nb_dir")) {
+            if (in.remaining()) nbdir = in.pop().to_integer();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "nb_comb")) {
+            if (in.remaining()) nbcomb = in.pop().to_integer();
+            else THROW_BADARG("missing value for " << opt);
+          } else if (cmd_strmatch(opt, "non-smooth")) nonsmooth = true;
+          else if (cmd_strmatch(opt, "noisy")) noisy = 1;
++>>>>>>> upstream
           else if (cmd_strmatch(opt, "very noisy") ||
                    cmd_strmatch(opt, "very_noisy")) noisy = 2;
           else THROW_BADARG("bad option: " << opt);
         }
  
++<<<<<<< HEAD
 +       if (md->model().is_complex())
 +	 THROW_BADARG("Sorry, the continuation has only a real version.");
 +
 +       getfem::cont_struct_getfem_model *ps;
 +       if (with_parametrized_data) {
 +	 getfem::cont_struct_getfem_model *ps1 =
 +	   new getfem::cont_struct_getfem_model
 +	   (md->model(), dataname_parameter, dataname_init, dataname_final,
 +	    dataname_current,
 +	    getfem::rselect_linear_solver(md->model(), lsolver), scfac,
 +	    maxit, thrit, maxres, maxdiff, minang, h_init, h_max, h_min,
 +	    h_inc, h_dec, epsilon, maxres_solve, noisy, nb_test);
++=======
+        getfem::cont_struct_getfem_model *ps;
+        if (!with_parametrised_data) {
+ 	 getfem::cont_struct_getfem_model *ps1 =
+ 	   new getfem::cont_struct_getfem_model
+            (md->model(), dataname_parameter, scfac,
+ 	    getfem::rselect_linear_solver(md->model(), lsolver),
+ 	    bifurcations, h_init, h_max, h_min, h_inc, h_dec, maxit, thrit,
+ 	    maxres, maxdiff, mincos, maxres_solve, noisy, nonsmooth,
+ 	    delta_max, delta_min, thrvar, nbdir, nbcomb);
++>>>>>>> upstream
  	 ps = ps1;
         }
         else {
  	 getfem::cont_struct_getfem_model *ps1 =
  	   new getfem::cont_struct_getfem_model
++<<<<<<< HEAD
 +           (md->model(), dataname_parameter,
 +	    getfem::rselect_linear_solver(md->model(), lsolver), scfac,
 +	    maxit, thrit, maxres, maxdiff, minang, h_init, h_max, h_min,
 +	    h_inc, h_dec, epsilon, maxres_solve, noisy, nb_test);
++=======
+ 	   (md->model(), dataname_parameter, dataname_init, dataname_final,
+ 	    dataname_current, scfac,
+ 	    getfem::rselect_linear_solver(md->model(), lsolver),
+ 	    bifurcations, h_init, h_max, h_min, h_inc, h_dec, maxit, thrit,
+ 	    maxres, maxdiff, mincos, maxres_solve, noisy, nonsmooth,
+ 	    delta_max, delta_min, thrvar, nbdir, nbcomb);
++>>>>>>> upstream
  	 ps = ps1;
         }
  
diff --cc interface/src/gf_cont_struct_get.cc
index 76a4e09,74c43db..3913317
--- a/interface/src/gf_cont_struct_get.cc
+++ b/interface/src/gf_cont_struct_get.cc
@@@ -65,104 -65,122 +65,219 @@@ void gf_cont_struct_get(getfemint::mexa
  
    if (subc_tab.size() == 0) {
    
++<<<<<<< HEAD
 +
 +    /*@FUNC t = ('init test function', @vec tangent, @scalar tangent_parameter)
 +      Initialise the border of the bordered system that serves for calculating
 +      the test function. Return the value of test function for the solution
 +      and the value of the parameter saved in the corresponding model object
 +      and the tangent given by `tangent` and `tangent_parameter`.@*/
 +    sub_command
 +      ("init test function", 2, 2, 0, 1,
 +
 +       size_type nbdof = ps->linked_model().nb_dof();
 +       std::vector<double> yy(nbdof); ps->linked_model().from_variables(yy);
 +       const getfem::model_real_plain_vector &GAMMA =
 +       ps->linked_model().real_variable(ps->parameter_name());
 +       GMM_ASSERT1(gmm::vect_size(GAMMA) == 1,
 +                   "The continuation parameter should be a real scalar!");
 +       scalar_type gamma = GAMMA[0];
 +       darray t_y = in.pop().to_darray();
 +       std::vector<double> tt_y(nbdof); gmm::copy(t_y, tt_y);
 +       scalar_type t_gamma = in.pop().to_scalar();
 +
 +       getfem::init_test_function(*ps, yy, gamma, tt_y, t_gamma);
 +       out.pop().from_scalar(ps->tau2());
 +       );
 +  
 +
 +    /*@FUNC E = ('init Moore-Penrose continuation', @scalar init_dir)
 +      Initialise the Moore-Penrose continuation: Return a unit tangent
 +      corresponding to the solution branch at the solution and the
 +      value of the parameter saved in the corresponding model object,
 +      and an initial step size for the continuation. Direction of the
 +      computed tangent with respect to the parameter is determined by the
 +      sign of `init_dir`.@*/
 +    sub_command
 +      ("init Moore-Penrose continuation", 1, 1, 0, 3,
 +
 +       size_type nbdof = ps->linked_model().nb_dof();
 +       std::vector<double> yy(nbdof); ps->linked_model().from_variables(yy);
 +       const getfem::model_real_plain_vector &GAMMA
 +       = ps->linked_model().real_variable(ps->parameter_name());
 +       GMM_ASSERT1(gmm::vect_size(GAMMA) == 1,
 +                   "The continuation parameter should be a real scalar!");
 +       scalar_type gamma = GAMMA[0];
 +       std::vector<double> tt_y(nbdof);
 +       scalar_type t_gamma = in.pop().to_scalar();
 +       scalar_type h;
 +
 +       getfem::init_Moore_Penrose_continuation(*ps, yy, gamma,
 +					       tt_y, t_gamma, h);
 +       out.pop().from_dcvector(tt_y);
++=======
+     
+     /*@FUNC h = ('init step size')
+       Return an initial step size for continuation.@*/
+     sub_command
+       ("init step size", 0, 0, 0, 1,
+        
+        out.pop().from_scalar(ps->h_init());
+        );
+   
+     
+     /*@FUNC t = ('init test function', @vec solution, @scalar parameter, @vec tangent_sol, @scalar tangent_par)
+       Initialise the border of the bordered system that serves for
+       calculating the test function for bifurcations. Return the value of the
+       test function for the point given by `solution` and `parameter` and the
+       tangent given by `tangent_sol` and `tangent_par`.@*/
+     sub_command
+       ("init test function", 4, 4, 0, 1,
+        
+        size_type nbdof = ps->linked_model().nb_dof();
+        darray x = in.pop().to_darray();
+        std::vector<double> xx(nbdof); gmm::copy(x, xx);
+        scalar_type gamma = in.pop().to_scalar();
+        darray t_x = in.pop().to_darray();
+        std::vector<double> tt_x(nbdof); gmm::copy(t_x, tt_x);
+        scalar_type t_gamma = in.pop().to_scalar();
+ 
+        getfem::init_test_function(*ps, xx, gamma, tt_x, t_gamma);
+        out.pop().from_scalar(ps->get_tau2());
+        );
+   
+ 
+     /*@FUNC E = ('init Moore-Penrose continuation', @vec solution, @scalar parameter, @scalar init_dir)
+       Initialise the Moore-Penrose continuation: Return a unit tangent to
+       the solution curve at the point given by `solution` and `parameter`,
+       and an initial step size for the continuation. Orientation of the
+       computed tangent with respect to the parameter is determined by the
+       sign of `init_dir`.@*/
+     sub_command
+       ("init Moore-Penrose continuation", 3, 3, 0, 3,
+ 
+        size_type nbdof = ps->linked_model().nb_dof();
+        darray x = in.pop().to_darray();
+        std::vector<double> xx(nbdof); gmm::copy(x, xx);
+        scalar_type gamma = in.pop().to_scalar();
+        std::vector<double> tt_x(nbdof);
+        scalar_type t_gamma = in.pop().to_scalar();
+        scalar_type h;
+ 
+        getfem::init_Moore_Penrose_continuation(*ps, xx, gamma,
+ 					       tt_x, t_gamma, h);
+        out.pop().from_dcvector(tt_x);
++>>>>>>> upstream
         out.pop().from_scalar(t_gamma);
         out.pop().from_scalar(h);
         );
  
  
++<<<<<<< HEAD
 +    /*@FUNC E = ('Moore-Penrose continuation', @vec tangent, @scalar tangent_parameter, @scalar h)
 +      Compute one step of the Moore-Penrose continuation: Take the solution
 +      and the value of the parameter saved in the corresponding model object,
 +      the tangent given by `tangent` and `tangent_parameter`, and the step
 +      size `h`, save a new point on the solution curve into the model object,
 +      and return a new tangent and a step size for the next step. If the
 +      returned step size equals zero, the continuation has failed.@*/
 +    sub_command
 +      ("Moore-Penrose continuation", 3, 3, 0, 3,
 +
 +       size_type nbdof = ps->linked_model().nb_dof();
 +       std::vector<double> yy(nbdof); ps->linked_model().from_variables(yy);
 +       const getfem::model_real_plain_vector &GAMMA
 +       = ps->linked_model().real_variable(ps->parameter_name());
 +       GMM_ASSERT1(gmm::vect_size(GAMMA) == 1,
 +                   "The continuation parameter should be a real scalar!");
 +       scalar_type gamma = GAMMA[0];
 +       darray t_y = in.pop().to_darray();
 +       std::vector<double> tt_y(nbdof); gmm::copy(t_y, tt_y);
 +       scalar_type t_gamma = in.pop().to_scalar();
 +       scalar_type h = in.pop().to_scalar();
 +
 +       getfem::Moore_Penrose_continuation(*ps, yy, gamma, tt_y, t_gamma, h);
 +       out.pop().from_dcvector(tt_y);
 +       out.pop().from_scalar(t_gamma);
 +       out.pop().from_scalar(h);
++=======
+     /*@FUNC E = ('Moore-Penrose continuation', @vec solution, @scalar parameter, @vec tangent_sol, @scalar tangent_par, @scalar h)
+       Compute one step of the Moore-Penrose continuation: Take the point
+       given by `solution` and `parameter`, the tangent given by `tangent_sol`
+       and `tangent_par`, and the step size `h`. Return a new point on the
+       solution curve, the corresponding tangent and a step size for the next
+       step. If the returned step size equals zero, the continuation has
+       failed. Optionally, return the type of any detected bifurcation point.
+       NOTE: The new point need not to be saved in the model in the end!@*/
+     sub_command
+       ("Moore-Penrose continuation", 5, 5, 0, 6,
+ 
+        size_type nbdof = ps->linked_model().nb_dof();
+        darray x = in.pop().to_darray();
+        std::vector<double> xx(nbdof); gmm::copy(x, xx);
+        scalar_type gamma = in.pop().to_scalar();
+        darray t_x = in.pop().to_darray();
+        std::vector<double> tt_x(nbdof); gmm::copy(t_x, tt_x);
+        scalar_type t_gamma = in.pop().to_scalar();
+        scalar_type h = in.pop().to_scalar();
+ 
+        getfem::Moore_Penrose_continuation(*ps, xx, gamma, tt_x, t_gamma, h);
+        out.pop().from_dcvector(xx);
+        out.pop().from_scalar(gamma);
+        out.pop().from_dcvector(tt_x);
+        out.pop().from_scalar(t_gamma);
+        out.pop().from_scalar(h);
+        if (out.remaining())
+ 	 out.pop().from_string(ps->get_sing_label().c_str());
++>>>>>>> upstream
         );
  
  
      /*@GET t = ('test function')
++<<<<<<< HEAD
 +      Return the last value of the test function and eventaully all the
 +      values calculated when passing through a boundary between different
 +      smooth pieces.@*/
 +    sub_command
 +      ("test function", 0, 0, 0, 2,
 +       out.pop().from_scalar(ps->tau2());
++=======
+       Return the last value of the test function and eventaully the whole
+       calculated graph when passing between subdomains of different smooth
+       pieces.@*/
+     sub_command
+       ("test function", 0, 0, 0, 3,
+        out.pop().from_scalar(ps->get_tau2());
+        if (out.remaining()) out.pop().from_dcvector(ps->get_alpha_hist());
++>>>>>>> upstream
         if (out.remaining()) out.pop().from_dcvector(ps->get_tau_hist());
         );
  
  
++<<<<<<< HEAD
 +    /*@GET s = ('char')
 +      Output a (unique) string representation of the @tcs.
 +
 +      This can be used to perform comparisons between two
++=======
+     /*@GET @CELL{X, gamma, T_X, T_gamma} = ('sing_data')
+       Return a singular point (`X`, `gamma`) encountered in the last
+       continuation step (if any) and a couple of arrays (`T_X`, `T_gamma`) of
+       tangents to all located solution branches, which emanate from there.@*/
+     sub_command
+       ("sing_data", 0, 0, 0, 4,
+        out.pop().from_dcvector(ps->get_x_sing());
+        out.pop().from_scalar(ps->get_gamma_sing());
+        out.pop().from_vector_container(ps->get_t_x_sing());
+        out.pop().from_dcvector(ps->get_t_gamma_sing());
+        );
+ 
+ 
+     /*@GET s = ('char')
+       Output a (unique) string representation of the @tcs.
+ 
+       This can be used for performing comparisons between two
++>>>>>>> upstream
        different @tcs objects.
        This function is to be completed.
        @*/
diff --cc interface/src/gf_mesh_im.cc
index 83a64e7,f5f90ac..3c17995
--- a/interface/src/gf_mesh_im.cc
+++ b/interface/src/gf_mesh_im.cc
@@@ -134,6 -134,28 +134,31 @@@ void gf_mesh_im(getfemint::mexargs_in& 
        the levelset, it has to be chosen among 'ALL', 'INSIDE', 'OUTSIDE' and
        'BOUNDARY'.
  
++<<<<<<< HEAD
++=======
+       it can be completed by a string defining the boolean operation
+       to define the integration domain when there is more than one levelset.
+ 
+       the syntax is very simple, for example if there are 3 different
+       levelset,
+        
+        "a*b*c" is the intersection of the domains defined by each
+        levelset (this is the default behaviour if this function is not
+        called).
+ 
+        "a+b+c" is the union of their domains.
+ 
+        "c-(a+b)" is the domain of the third levelset minus the union of
+        the domains of the two others.
+        
+        "!a" is the complementary of the domain of a (i.e. it is the
+        domain where a(x)>0)
+ 
+        The first levelset is always referred to with "a", the second
+        with "b", and so on.
+       for intance INSIDE(a*b*c)
+ 
++>>>>>>> upstream
        CAUTION: this integration method will be defined only on the element
        cut by the level-set. For the 'ALL', 'INSIDE' and 'OUTSIDE' options
        it is mandatory to use the method ``MESH_IM:SET('integ')`` to define
diff --cc interface/src/gf_model_get.cc
index b3eaf35,4dcb148..a10cbb3
--- a/interface/src/gf_model_get.cc
+++ b/interface/src/gf_model_get.cc
@@@ -1,6 -1,6 +1,10 @@@
  /*===========================================================================
   
++<<<<<<< HEAD
 + Copyright (C) 2009-2012 Yves Renard.
++=======
+  Copyright (C) 2009-2013 Yves Renard.
++>>>>>>> upstream
   
   This file is a part of GETFEM++
   
@@@ -204,9 -204,12 +208,18 @@@ void gf_model_get(getfemint::mexargs_in
         const getfem::mesh_fem &mf = md->model().mesh_fem_of_variable(name);
         getfem::mesh_fem *mmf = const_cast<getfem::mesh_fem *>(&mf);
         getfem_object *o =
++<<<<<<< HEAD
 +       getfemint::workspace().object(getfem_object::internal_key_type(mmf));
 +       getfemint_mesh_fem *gmf = getfemint_mesh_fem::get_from(mmf);
 +       if (!o) workspace().set_dependance(gmf, md);
++=======
+          getfemint::workspace().object(getfem_object::internal_key_type(mmf));
+        getfemint_mesh_fem *gmf = getfemint_mesh_fem::get_from(mmf);
+        if (!o) {
+          gmf->set_flags(STATIC_OBJ);
+          workspace().set_dependance(gmf, md);
+        }
++>>>>>>> upstream
         out.pop().from_object_id(gmf->get_id(), MESHFEM_CLASS_ID);
         );
  
@@@ -343,7 -346,7 +356,11 @@@
           else if (cmd_strmatch(opt, "with pseudo potential"))
             with_pseudo_pot = true;
           else if (cmd_strmatch(opt, "very noisy") ||
++<<<<<<< HEAD
 +                  cmd_strmatch(opt, "very_noisy")) iter.set_noisy(2);
++=======
+                   cmd_strmatch(opt, "very_noisy")) iter.set_noisy(3);
++>>>>>>> upstream
           else if (cmd_strmatch(opt, "max_iter")) {
             if (in.remaining()) iter.set_maxiter(in.pop().to_integer());
             else THROW_BADARG("missing value for " << opt);
@@@ -371,10 -374,18 +388,25 @@@
           } else THROW_BADARG("bad option: " << opt);
         }
  
++<<<<<<< HEAD
 +       getfem::default_newton_line_search default_ls;
 +       getfem::simplest_newton_line_search simplest_ls(size_type(-1), alpha_max_ratio, alpha_min, alpha_mult);
 +       getfem::systematic_newton_line_search systematic_ls(size_type(-1), alpha_min, alpha_mult);
 +       getfem::basic_newton_line_search basic_ls(size_type(-1), alpha_min, alpha_mult);
++=======
+        // default values in sync with getfem_model_solvers.h
+        if (alpha_max_ratio < scalar_type(0))
+          alpha_max_ratio = (lsearch == "basic") ?  5.0/3.0 : 6.0/5.0;
+        if (alpha_min < scalar_type(0))
+          alpha_min = (lsearch == "systematic") ? 1.0/10000.0 : 1.0/1000.0;
+        if (alpha_mult < scalar_type(0))
+          alpha_mult = 3.0/5.0;
+ 
+        getfem::default_newton_line_search default_ls;
+        getfem::simplest_newton_line_search simplest_ls(size_type(-1), alpha_max_ratio, alpha_min, alpha_mult);
+        getfem::systematic_newton_line_search systematic_ls(size_type(-1), alpha_min, alpha_mult);
+        getfem::basic_newton_line_search basic_ls(size_type(-1), alpha_max_ratio, alpha_min, alpha_mult);
++>>>>>>> upstream
         getfem::quadratic_newton_line_search quadratic_ls(size_type(-1));
  
         getfem::abstract_newton_line_search *ls = 0;
@@@ -402,80 -413,185 +434,262 @@@
                                  getfem::cselect_linear_solver(md->model(),
                                                                lsolver),
                                  *ls, with_pseudo_pot);
++<<<<<<< HEAD
 +       }
 +       if (out.remaining()) out.pop().from_integer(int(iter.get_iteration()));
 +       if (out.remaining()) out.pop().from_integer(int(iter.converged()));
 +       );
 +
 +
 +    /*@GET ('test tangent matrix'[, @scalar EPS[, @int NB[, @scalar scale]]])
 +      Test the consistency of the tangent matrix in some random positions
 +      and random directions (useful to test newly created bricks).
 +      `EPS` is the value of the small parameter for the finite difference
 +      computation of the derivative is the random direction (default is 1E-6).
 +      `NN` is the number of tests (default is 100). `scale` is a parameter
 +      for the random position (default is 1). Each dof od the random
 +      position is chosen in the range [-scale, scale].
 +      @*/
 +    sub_command
 +      ("test tangent matrix", 0, 3, 0, 1,
 +       size_type nbdof = md->model().nb_dof();
 +       scalar_type EPS = 1E-6;
 +       if (in.remaining()) EPS = in.pop().to_scalar();
 +       scalar_type errmax = scalar_type(0);
 +       size_type NN = 100;
 +       if (in.remaining()) NN = in.pop().to_integer();
 +       scalar_type scale = scalar_type(1);
 +       if (in.remaining()) scale = in.pop().to_scalar();
 +
 +       if (md->model().is_linear())
 +	 cout << "Problem is linear, the test is not relevant";
 +       else {
 +	 if (md->is_complex()) {
 +	   std::vector<complex_type> U(nbdof);
 +	   std::vector<complex_type> DIR(nbdof);
 +	   std::vector<complex_type> D1(nbdof);
 +	   std::vector<complex_type> D2(nbdof);
 +	   for (size_type i = 0; i < NN; ++i) {
 +	     gmm::fill_random(U); gmm::scale(U, scale);
 +	     gmm::fill_random(DIR); gmm::scale(DIR, scale);
 +	     md->model().to_variables(U);
 +	     md->model().assembly(getfem::model::BUILD_ALL);
 +	     gmm::copy(md->model().complex_rhs(), D2);
 +	     gmm::mult(md->model().complex_tangent_matrix(), DIR, D1);
 +	     gmm::add(gmm::scaled(DIR, complex_type(EPS)), U);
 +	     md->model().to_variables(U);
 +	     md->model().assembly(getfem::model::BUILD_RHS);
 +	     gmm::add(gmm::scaled(md->model().complex_rhs(),
 +				  -complex_type(1)), D2);
 +	     gmm::scale(D2, complex_type(1)/complex_type(EPS));
 +	     scalar_type err = gmm::vect_dist2(D1, D2);
 +	     cout << "Error at step " << i << " : " << err << endl;
 +	     errmax = std::max(err, errmax);
 +	   }
 +	 } else {
 +	   std::vector<scalar_type> U(nbdof);
 +	   std::vector<scalar_type> DIR(nbdof);
 +	   std::vector<scalar_type> D1(nbdof);
 +	   std::vector<scalar_type> D2(nbdof);
 +	   for (size_type i = 0; i < NN; ++i) {
 +	     gmm::fill_random(U); gmm::scale(U, scale);
 +	     gmm::fill_random(DIR); gmm::scale(DIR, scale);
 +	     md->model().to_variables(U);
 +	     md->model().assembly(getfem::model::BUILD_ALL);
 +	     gmm::copy(md->model().real_rhs(), D2);
 +	     gmm::mult(md->model().real_tangent_matrix(), DIR, D1);
 +	     gmm::add(gmm::scaled(DIR, EPS), U);
 +	     md->model().to_variables(U);
 +	     md->model().assembly(getfem::model::BUILD_RHS);
 +	     gmm::add(gmm::scaled(md->model().real_rhs(),-scalar_type(1)), D2);
 +	     gmm::scale(D2, scalar_type(1)/EPS);
 +	     scalar_type err = gmm::vect_dist2(D1, D2);
 +	     cout << "Error at step " << i << " : " << err << endl;
 +	     errmax = std::max(err, errmax);
 +	   }
 +	 }
 +       }
++=======
+        }
+        if (out.remaining()) out.pop().from_integer(int(iter.get_iteration()));
+        if (out.remaining()) out.pop().from_integer(int(iter.converged()));
+        );
+ 
+ 
+     /*@GET ('test tangent matrix'[, @scalar EPS[, @int NB[, @scalar scale]]])
+       Test the consistency of the tangent matrix in some random positions
+       and random directions (useful to test newly created bricks).
+       `EPS` is the value of the small parameter for the finite difference
+       computation of the derivative is the random direction (default is 1E-6).
+       `NN` is the number of tests (default is 100). `scale` is a parameter
+       for the random position (default is 1, 0 is an acceptable value) around
+       the current position.
+       Each dof of the random position is chosen in the range
+       [current-scale, current+scale].
+       @*/
+     sub_command
+       ("test tangent matrix", 0, 3, 0, 1,
+        size_type nbdof = md->model().nb_dof();
+        scalar_type EPS = 1E-6;
+        if (in.remaining()) EPS = in.pop().to_scalar();
+        scalar_type errmax = scalar_type(0);
+        size_type NN = 100;
+        if (in.remaining()) NN = in.pop().to_integer();
+        scalar_type scalef = scalar_type(1);
+        if (in.remaining()) scalef = in.pop().to_scalar();
+ 
+        if (md->model().is_linear()) {
+ 	 GMM_WARNING1("Problem is linear, the test is not relevant");
+        } else {
+ 	 if (md->is_complex()) {
+ 	   std::vector<complex_type> U(nbdof);
+ 	   std::vector<complex_type> dU(nbdof);
+ 	   std::vector<complex_type> DIR(nbdof);
+ 	   std::vector<complex_type> D1(nbdof);
+ 	   std::vector<complex_type> D2(nbdof);
+            md->model().from_variables(U);
+ 	   for (size_type i = 0; i < NN; ++i) {
+ 	     gmm::fill_random(dU); gmm::scale(dU, complex_type(scalef));
+              gmm::add(U, dU);
+ 	     gmm::fill_random(DIR);
+ 	     md->model().to_variables(dU);
+ 	     md->model().assembly(getfem::model::BUILD_ALL);
+ 	     gmm::copy(md->model().complex_rhs(), D2);
+ 	     gmm::mult(md->model().complex_tangent_matrix(), DIR, D1);
+ 	     gmm::add(gmm::scaled(DIR, complex_type(EPS)), dU);
+ 	     md->model().to_variables(dU);
+ 	     md->model().assembly(getfem::model::BUILD_RHS);
+ 	     gmm::add(gmm::scaled(md->model().complex_rhs(),
+ 				  -complex_type(1)), D2);
+ 	     gmm::scale(D2, complex_type(1)/complex_type(EPS));
+ 	     scalar_type err = gmm::vect_dist2(D1, D2);
+ 	     cout << "Error at step " << i << " : " << err << endl;
+ 	     errmax = std::max(err, errmax);
+ 	   }
+            md->model().to_variables(U);
+ 	 } else {
+ 	   std::vector<scalar_type> U(nbdof);
+ 	   std::vector<scalar_type> dU(nbdof);
+ 	   std::vector<scalar_type> DIR(nbdof);
+ 	   std::vector<scalar_type> D1(nbdof);
+ 	   std::vector<scalar_type> D2(nbdof);
+            md->model().from_variables(U);
+ 	   for (size_type i = 0; i < NN; ++i) {
+ 	     gmm::fill_random(dU); gmm::scale(dU, scalef);
+              gmm::add(U, dU);
+ 	     gmm::fill_random(DIR);
+ 	     md->model().to_variables(dU);
+ 	     md->model().assembly(getfem::model::BUILD_ALL);
+ 	     gmm::copy(md->model().real_rhs(), D2);
+ 	     gmm::mult(md->model().real_tangent_matrix(), DIR, D1);
+ 	     gmm::add(gmm::scaled(DIR, EPS), dU);
+ 	     md->model().to_variables(dU);
+ 	     md->model().assembly(getfem::model::BUILD_RHS);
+ 	     gmm::add(gmm::scaled(md->model().real_rhs(),-scalar_type(1)), D2);
+ 	     gmm::scale(D2, scalar_type(1)/EPS);
+ 	     scalar_type err = gmm::vect_dist2(D1, D2);
+ 	     cout << "Error at step " << i << " : " << err << endl;
+ 	     errmax = std::max(err, errmax);
+ 	   }
+            md->model().to_variables(U);
+ 	 }
+        }
+        out.pop().from_scalar(errmax);
+        );
+ 
+ 
+     /*@GET ('test tangent matrix term', @str varname1, @str varname2[, @scalar EPS[, @int NB[, @scalar scale]]])
+       Test the consistency of a part of the tangent matrix in some
+       random positions and random directions
+       (useful to test newly created bricks).
+       The increment is only made on variable `varname2` and tested on the
+       part of the residual corresponding to `varname1`. This means that
+       only the term (`varname1`, `varname2`) of the tangent matrix is tested.
+       `EPS` is the value of the small parameter for the finite difference
+       computation of the derivative is the random direction (default is 1E-6).
+       `NN` is the number of tests (default is 100). `scale` is a parameter
+       for the random position (default is 1, 0 is an acceptable value)
+       around the current position.
+       Each dof of the random position is chosen in the range
+       [current-scale, current+scale].
+       @*/
+     sub_command
+       ("test tangent matrix term", 2, 5, 0, 1,
+        std::string varname1 = in.pop().to_string();
+        std::string varname2 = in.pop().to_string();
+        gmm::sub_interval I1 = md->model().interval_of_variable(varname1);
+        gmm::sub_interval I2 = md->model().interval_of_variable(varname2);
+        size_type nbdof1 = I1.size();
+        size_type nbdof2 = I2.size();
+ 
+        scalar_type EPS = 1E-6;
+        if (in.remaining()) EPS = in.pop().to_scalar();
+        scalar_type errmax = scalar_type(0);
+        size_type NN = 100;
+        if (in.remaining()) NN = in.pop().to_integer();
+        scalar_type scalef = scalar_type(1);
+        if (in.remaining()) scalef = in.pop().to_scalar();
+ 
+        if (md->model().is_linear()) {
+ 	 GMM_WARNING1("Problem is linear, the test is not relevant");
+        } else {
+ 	 if (md->is_complex()) {
+ 	   std::vector<complex_type> U2(nbdof2);
+ 	   std::vector<complex_type> dU2(nbdof2);
+ 	   std::vector<complex_type> DIR2(nbdof2);
+ 	   std::vector<complex_type> D1(nbdof1);
+ 	   std::vector<complex_type> D2(nbdof1);
+            gmm::copy(md->model().complex_variable(varname2), U2);
+ 	   for (size_type i = 0; i < NN; ++i) {
+ 	     gmm::fill_random(dU2); gmm::scale(dU2, complex_type(scalef));
+              gmm::add(U2, dU2);
+              gmm::copy(dU2, md->model().set_complex_variable(varname2));
+ 	     gmm::fill_random(DIR2);
+ 	     md->model().assembly(getfem::model::BUILD_ALL);
+ 	     gmm::copy(gmm::sub_vector(md->model().complex_rhs(), I1), D2);
+ 	     gmm::mult(gmm::sub_matrix(md->model().complex_tangent_matrix(),
+                                        I1, I2), DIR2, D1);
+ 	     gmm::add(gmm::scaled(DIR2, complex_type(EPS)), dU2);
+ 	     gmm::copy(dU2, md->model().set_complex_variable(varname2));
+ 	     md->model().assembly(getfem::model::BUILD_RHS);
+ 	     gmm::add(gmm::scaled(gmm::sub_vector(md->model().complex_rhs(),
+                                                   I1), complex_type(-1)), D2);
+ 	     gmm::scale(D2, complex_type(1)/complex_type(EPS));
+ 	     scalar_type err = gmm::vect_dist2(D1, D2);
+ 	     cout << "Error at step " << i << " : " << err << endl;
+ 	     errmax = std::max(err, errmax);
+ 	   }
+            gmm::copy(U2, md->model().set_complex_variable(varname2));
+ 	 } else {
+ 	   std::vector<scalar_type> U2(nbdof2);
+ 	   std::vector<scalar_type> dU2(nbdof2);
+ 	   std::vector<scalar_type> DIR2(nbdof2);
+ 	   std::vector<scalar_type> D1(nbdof1);
+ 	   std::vector<scalar_type> D2(nbdof1);
+            gmm::copy(md->model().real_variable(varname2), U2);
+ 	   for (size_type i = 0; i < NN; ++i) {
+ 	     gmm::fill_random(dU2); gmm::scale(dU2, scalef);
+              gmm::add(U2, dU2);
+              gmm::copy(dU2, md->model().set_real_variable(varname2));
+ 	     gmm::fill_random(DIR2);
+ 	     md->model().assembly(getfem::model::BUILD_ALL);
+ 	     gmm::copy(gmm::sub_vector(md->model().real_rhs(), I1), D2);
+ 	     gmm::mult(gmm::sub_matrix(md->model().real_tangent_matrix(),
+                                        I1, I2), DIR2, D1);
+ 	     gmm::add(gmm::scaled(DIR2, scalar_type(EPS)), dU2);
+ 	     gmm::copy(dU2, md->model().set_real_variable(varname2));
+ 	     md->model().assembly(getfem::model::BUILD_RHS);
+ 	     gmm::add(gmm::scaled(gmm::sub_vector(md->model().real_rhs(),
+                                                   I1), scalar_type(-1)), D2);
+ 	     gmm::scale(D2, scalar_type(1)/EPS);
+ 	     scalar_type err = gmm::vect_dist2(D1, D2);
+ 	     cout << "Error at step " << i << " : " << err << endl;
+ 	     errmax = std::max(err, errmax);
+ 	   }
+            gmm::copy(U2, md->model().set_real_variable(varname2));
+ 	 }
+        }
++>>>>>>> upstream
         out.pop().from_scalar(errmax);
         );
  
@@@ -543,7 -660,8 +758,12 @@@
      /*@GET V = ('compute second Piola Kirchhoff tensor', @str varname, @str lawname, @str dataname, @tmf mf_sigma)
        Compute on `mf_sigma` the second Piola Kirchhoff stress tensor of a field
        for nonlinear elasticity in 3D. `lawname` is the constitutive law which
++<<<<<<< HEAD
 +      could be 'SaintVenant Kirchhoff', 'Mooney Rivlin' or 'Ciarlet Geymonat'.
++=======
+       could be 'SaintVenant Kirchhoff', 'Mooney Rivlin', 'neo Hookean' or
+       'Ciarlet Geymonat'.
++>>>>>>> upstream
        `dataname` is a vector of parameters for the constitutive law. Its length
        depends on the law. It could be a short vector of constant values or a
        vector field described on a finite element method for variable
diff --cc interface/src/gf_model_set.cc
index 57bb8fd,3bfe88a..fba2efd
--- a/interface/src/gf_model_set.cc
+++ b/interface/src/gf_model_set.cc
@@@ -578,6 -671,52 +671,55 @@@ void gf_model_set(getfemint::mexargs_in
         ind += getfem::add_normal_Dirichlet_condition_with_penalization
         (md->model(), gfi_mim->mesh_im(), varname, coeff, region,
          dataname, mf_mult);
++<<<<<<< HEAD
++=======
+        workspace().set_dependance(md, gfi_mim);
+        out.pop().from_integer(int(ind));
+        );
+ 
+ 
+     /*@SET ind = ('add normal Dirichlet condition with Nitsche method', @tmim mim, @str varname, @str gamma0name, @int region[, @scalar theta][, @str dataname])
+       Add a Dirichlet condition to the normal component of the vector
+       (or tensor) valued variable `varname` and the mesh region `region`.
+       This region should be a boundary. The Dirichlet
+       condition is prescribed with Nitsche's method. `dataname` is the optional
+       right hand side of the Dirichlet condition. It could be constant or
+       described on a fem. `gamma0name` is the
+       Nitsche's method parameter. `theta` is a scalar value which can be
+       positive or negative. `theta = 1` corresponds to the standard symmetric
+       method which is conditionnaly coercive for  `gamma0` small.
+       `theta = -1` corresponds to the skew-symmetric method which is
+       inconditionnaly coercive. `theta = 0` is the simplest method
+       for which the second derivative of the Neumann term is not necessary
+       even for nonlinear problems. 
+       CAUTION: This brick has to be added in the model after all the bricks
+       corresponding to partial differential terms having a Neumann term.
+       Moreover, This brick can only be applied to bricks declaring their
+       Neumann terms. Returns the brick index in the model.
+       (This brick is not fully tested)
+     @*/
+     sub_command
+       ("add normal Dirichlet condition with Nitsche method", 4, 6, 0, 1,
+        getfemint_mesh_im *gfi_mim = in.pop().to_getfemint_mesh_im();
+        std::string varname = in.pop().to_string();
+        std::string gamma0name = in.pop().to_string();
+        size_type region = in.pop().to_integer();
+        scalar_type theta = scalar_type(1);
+        std::string dataname;
+        if (in.remaining()) {
+ 	 mexarg_in argin = in.pop();
+ 	 if (argin.is_string())
+ 	   dataname = argin.to_string();
+ 	 else
+ 	   theta = argin.to_scalar();
+        }
+        if (in.remaining()) dataname = in.pop().to_string();
+ 
+        size_type ind = config::base_index();
+        ind += getfem::add_normal_Dirichlet_condition_with_Nitsche_method
+        (md->model(), gfi_mim->mesh_im(), varname, gamma0name, region,
+ 	theta, dataname);
++>>>>>>> upstream
         workspace().set_dependance(md, gfi_mim);
         out.pop().from_integer(int(ind));
         );
@@@ -680,6 -819,58 +822,61 @@@
         );
  
  
++<<<<<<< HEAD
++=======
+     /*@SET ind = ('add generalized Dirichlet condition with Nitsche method', @tmim mim, @str varname, @str gamma0name, @int region[, @scalar theta], @str dataname, @str Hname)
+       Add a Dirichlet condition on the variable `varname` and the mesh
+       region `region`.
+       This version is for vector field. It prescribes a condition
+       @f$ Hu = r @f$ where `H` is a matrix field.
+       CAUTION : the matrix H should have all eigenvalues equal to 1 or 0.
+       The region should be a
+       boundary. This region should be a boundary.  The Dirichlet
+       condition is prescribed with Nitsche's method. `dataname` is the optional
+       right hand side of the Dirichlet condition. It could be constant or
+       described on a fem. `gamma0name` is the
+       Nitsche's method parameter. `theta` is a scalar value which can be
+       positive or negative. `theta = 1` corresponds to the standard symmetric
+       method which is conditionnaly coercive for  `gamma0` small.
+       `theta = -1` corresponds to the skew-symmetric method which is
+       inconditionnaly coercive. `theta = 0` is the simplest method
+       for which the second derivative of the Neumann term is not necessary
+       even for nonlinear problems. `Hname' is the data
+       corresponding to the matrix field `H`. It has to be a constant matrix
+       or described on a scalar fem.
+       CAUTION: This brick has to be added in the model after all the bricks
+       corresponding to partial differential terms having a Neumann term.
+       Moreover, This brick can only be applied to bricks declaring their
+       Neumann terms. Returns the brick index in the model.
+       (This brick is not fully tested)
+     @*/
+     sub_command
+       ("add generalized Dirichlet condition with Nitsche method", 6, 7, 0, 1,
+        getfemint_mesh_im *gfi_mim = in.pop().to_getfemint_mesh_im();
+        std::string varname = in.pop().to_string();
+        std::string gamma0name = in.pop().to_string();
+        size_type region = in.pop().to_integer();
+        scalar_type theta = scalar_type(1);
+        std::string dataname;
+        if (in.remaining()) {
+ 	 mexarg_in argin = in.pop();
+ 	 if (argin.is_string())
+ 	   dataname = argin.to_string();
+ 	 else
+ 	   theta = argin.to_scalar();
+        }
+        dataname = in.pop().to_string();
+        std::string Hname= in.pop().to_string();
+ 
+        size_type ind = config::base_index();
+        ind += getfem::add_generalized_Dirichlet_condition_with_Nitsche_method
+        (md->model(), gfi_mim->mesh_im(), varname, gamma0name, region,
+ 	theta, dataname, Hname);
+        workspace().set_dependance(md, gfi_mim);
+        out.pop().from_integer(int(ind));
+        );
+ 
++>>>>>>> upstream
      /*@SET ind = ('add pointwise constraints with multipliers', @str varname, @str dataname_pt[, @str dataname_unitv] [, @str dataname_val])
      Add some pointwise constraints on the variable `varname` using
      multiplier. The multiplier variable is automatically added to the model.
@@@ -1168,8 -1359,15 +1365,20 @@@
      /*@SET ind = ('add nonlinear elasticity brick', @tmim mim, @str varname, @str constitutive_law, @str dataname[, @int region])
      Add a nonlinear elasticity term to the model relatively to the
      variable `varname`. `lawname` is the constitutive law which
++<<<<<<< HEAD
 +    could be 'SaintVenant Kirchhoff', 'Mooney Rivlin', 'Ciarlet Geymonat'
 +    or 'generalized Blatz Ko'.
++=======
+     could be 'SaintVenant Kirchhoff', 'Mooney Rivlin', 'neo Hookean',
+     'Ciarlet Geymonat' or 'generalized Blatz Ko'.
+     'Mooney Rivlin' and 'neo Hookean' law names can be preceded with the word
+     'compressible' or 'incompressible' to force using the corresponding version.
+     The compressible version of these laws requires one additional material
+     coefficient. By default, the incompressible version of 'Mooney Rivlin' law
+     and the compressible one of the 'neo Hookean' law are considered. In general,
+     'neo Hookean' is a special case of the 'Mooney Rivlin' law that requires one
+     coefficient less.
++>>>>>>> upstream
      IMPORTANT : if the variable is defined on a 2D mesh, the plane strain
      approximation is automatically used.
      `dataname` is a vector of parameters for the constitutive law. Its length
@@@ -1619,6 -1817,6 +1828,8 @@@
          dal::bit_vector bv = in.pop().to_bit_vector();
          for (dal::bv_visitor ii(bv); !ii.finished(); ++ii)
            md->model().enable_brick(ii);
++<<<<<<< HEAD
++=======
          );
  
       /*@SET ('disable variable', @str varname)
@@@ -1639,9 -1837,9 +1850,33 @@@
         ("enable variable", 1, 1, 0, 0,
          std::string varname = in.pop().to_string();
  	md->model().enable_variable(varname);
++>>>>>>> upstream
 +        );
 +
++     /*@SET ('disable variable', @str varname)
++       Disable a variable for a solve. The next solve will operate only on
++       the remaining variables. This allows to solve separately different
++       parts of a model. If there is a strong coupling of the variables,
++       a fixed point strategy can the be used. @*/
++     sub_command
++       ("disable variable", 1, 1, 0, 0,
++	std::string varname = in.pop().to_string();
++	md->model().disable_variable(varname);
++        );
++
++<<<<<<< HEAD
++
++     /*@SET ('enable variable', @str varname)
++       Enable a disabled variable. @*/
++     sub_command
++       ("enable variable", 1, 1, 0, 0,
++        std::string varname = in.pop().to_string();
++	md->model().enable_variable(varname);
+         );
  
+ 
++=======
++>>>>>>> upstream
       /*@SET ('first iter')
         To be executed before the first iteration of a time integration
         scheme. @*/
@@@ -1660,9 -1858,9 +1895,15 @@@
          );
  
  
++<<<<<<< HEAD
 +     /*@SET ind = ('add basic contact brick', @str varname_u, @str multname_n[, @str multname_t], @str dataname_r, @tspmat BN[, @tspmat BT, @str dataname_friction_coeff][, @str dataname_gap[, @str dataname_alpha[, @int augmented_version]])
 +       
 +     Add a contact with  or without friction brick to the model.
++=======
+      /*@SET ind = ('add basic contact brick', @str varname_u, @str multname_n[, @str multname_t], @str dataname_r, @tspmat BN[, @tspmat BT, @str dataname_friction_coeff][, @str dataname_gap[, @str dataname_alpha[, @int augmented_version[, @str dataname_gamma, @str dataname_wt]]])
+        
+      Add a contact with or without friction brick to the model.
++>>>>>>> upstream
       If U is the vector
       of degrees of freedom on which the unilateral constraint is applied,
       the matrix `BN` have to be such that this constraint is defined by
@@@ -1691,7 -1889,7 +1932,11 @@@
       unsymmetric method with augmented multipliers, 4 for the unsymmetric
       method with augmented multipliers and De Saxce projection. @*/
       sub_command
++<<<<<<< HEAD
 +       ("add basic contact brick", 4, 10, 0, 1,
++=======
+        ("add basic contact brick", 4, 12, 0, 1,
++>>>>>>> upstream
  
          bool friction = false;
  
@@@ -1724,6 -1922,15 +1969,18 @@@
          int augmented_version = 1;
          if (in.remaining()) augmented_version = in.pop().to_integer(1,4);
  
++<<<<<<< HEAD
++=======
+         std::string dataname_gamma;
+         std::string dataname_wt;
+         if (in.remaining()) {
+           GMM_ASSERT1(friction,
+                       "gamma and wt parameters are for the frictional brick only");
+           dataname_gamma = in.pop().to_string();
+           dataname_wt = in.pop().to_string();
+         }
+ 
++>>>>>>> upstream
          getfem::CONTACT_B_MATRIX BBN;
          getfem::CONTACT_B_MATRIX BBT;
          if (BN->storage()==gsparse::CSCMAT) {
@@@ -1756,7 -1963,8 +2013,12 @@@
          if (friction) {
            ind = getfem::add_basic_contact_brick
              (md->model(), varname_u, multname_n, multname_t, dataname_r, BBN, BBT,
++<<<<<<< HEAD
 +             friction_coeff, dataname_gap, dataname_alpha, augmented_version);
++=======
+              friction_coeff, dataname_gap, dataname_alpha, augmented_version,
+              false, "", dataname_gamma, dataname_wt);
++>>>>>>> upstream
          } else {
            ind = getfem::add_basic_contact_brick
              (md->model(), varname_u, multname_n, dataname_r, BBN, dataname_gap,
@@@ -2017,45 -2225,171 +2279,213 @@@
          workspace().set_dependance(md, gfi_mim);
          out.pop().from_integer(int(ind + config::base_index()));
          );
++<<<<<<< HEAD
 +
 +
 +#ifdef EXPERIMENTAL_PURPOSE_ONLY
 +     /*@SET ind = ('add Nitsche contact with rigid obstacle brick',  @tmim mim, @str varname_u, @str dataname_obstacle, @str dataname_r, @str dataname_friction_coeff, @str dataname_lambda, @str dataname_mu, @int region)
 +
 +      Add a contact with friction condition with a rigid obstacle
 +      to the model with  Nitsche strategy (no multiplier) in an integral way.
 +      This is an experimental brick, which works only for linear homogeneous
 +      isotropic elasticity.
 +      The condition is applied on the variable `varname_u`
 +      on the boundary corresponding to `region`. The rigid obstacle should
 +      be described with the data `dataname_obstacle` being a signed distance
 +      to the obstacle (interpolated on a finite element method).
 +      The Nitsche parameter `dataname_r` should be chosen in a
 +      range of acceptable values. `dataname_friction_coeff` is the friction
 +      coefficient which could be constant or defined on a finite element
 +      method. `dataname_lambda` and `dataname_mu` are the Lame coefficients.
 +    @*/
 +     sub_command
 +       ("add Nitsche contact with rigid obstacle brick", 8, 8, 0, 1,
 +
 +        getfemint_mesh_im *gfi_mim = in.pop().to_getfemint_mesh_im();
 +        std::string varname_u = in.pop().to_string();
 +        std::string dataname_obs = in.pop().to_string();
 +        std::string dataname_r = in.pop().to_string();
 +        std::string dataname_coeff = in.pop().to_string();
 +        std::string dataname_lambda = in.pop().to_string();
 +        std::string dataname_mu = in.pop().to_string();
 +        size_type region = in.pop().to_integer();
 +
 +        size_type ind=
 +        getfem::add_Nitsche_contact_with_rigid_obstacle_brick
 +        (md->model(), gfi_mim->mesh_im(), varname_u, dataname_obs, dataname_r,
 +	 dataname_coeff, dataname_lambda, dataname_mu, region);
 +        workspace().set_dependance(md, gfi_mim);
 +        out.pop().from_integer(int(ind + config::base_index()));
 +        );
 +#endif
 +
++=======
+      
+      /*@SET ind = ('add Nitsche contact with rigid obstacle brick', @tmim mim, @str varname, @str dataname_obstacle, @str gamma0name,  @int region[, @scalar theta[, @str dataname_friction_coeff[, @str dataname_alpha, @str dataname_wt]]])
+       Adds a contact condition with or without Coulomb friction on the variable
+       `varname` and the mesh boundary `region`. The contact condition
+       is prescribed with Nitsche's method. The rigid obstacle should
+       be described with the data `dataname_obstacle` being a signed distance to
+       the obstacle (interpolated on a finite element method).
+       `gamma0name` is the Nitsche's method parameter.
+       `theta` is a scalar value which can be
+       positive or negative. `theta = 1` corresponds to the standard symmetric
+       method which is conditionnaly coercive for  `gamma0` small.
+       `theta = -1` corresponds to the skew-symmetric method which is
+       inconditionnaly coercive. `theta = 0` is the simplest method
+       for which the second derivative of the Neumann term is not necessary.
+       The optional parameter `dataname_friction_coeff` is the friction
+       coefficient which could be constant or defined on a finite element
+       method.
+       CAUTION: This brick has to be added in the model after all the bricks
+       corresponding to partial differential terms having a Neumann term.
+       Moreover, This brick can only be applied to bricks declaring their
+       Neumann terms. Returns the brick index in the model.
+     @*/
+     sub_command
+       ("add Nitsche contact with rigid obstacle brick", 5, 9, 0, 1,
+        getfemint_mesh_im *gfi_mim = in.pop().to_getfemint_mesh_im();
+        std::string varname = in.pop().to_string();
+        std::string dataname_obs = in.pop().to_string();
+        std::string gamma0name = in.pop().to_string();
+        size_type region = in.pop().to_integer();
+ 
+        scalar_type theta = scalar_type(1);
+        std::string dataname_fr;
+        if (in.remaining()) {
+ 	 mexarg_in argin = in.pop();
+ 	 if (argin.is_string())
+ 	   dataname_fr = argin.to_string();
+ 	 else
+ 	   theta = argin.to_scalar();
+        }
+        if (in.remaining()) dataname_fr = in.pop().to_string();
+        std::string dataname_alpha;
+        if (in.remaining()) dataname_alpha = in.pop().to_string();
+        std::string dataname_wt;
+        if (in.remaining()) dataname_wt = in.pop().to_string();
+ 
+        size_type ind = config::base_index();
+        ind += getfem::add_Nitsche_contact_with_rigid_obstacle_brick
+        (md->model(), gfi_mim->mesh_im(), varname, dataname_obs,
+ 	gamma0name, theta,
+ 	dataname_fr, dataname_alpha, dataname_wt, region);
+        workspace().set_dependance(md, gfi_mim);
+        out.pop().from_integer(int(ind));
+        );
+ 
+ #ifdef EXPERIMENTAL_PURPOSE_ONLY
+      
+      /*@SET ind = ('add Nitsche midpoint contact with rigid obstacle brick', @tmim mim, @str varname, @str dataname_obstacle, @str gamma0name,  @int region, @scalar theta, @str dataname_friction_coeff, @str dataname_alpha, @str dataname_wt, @int option)
+       EXPERIMENTAL BRICK: for midpoint scheme only !!
+       Adds a contact condition with or without Coulomb friction on the variable
+       `varname` and the mesh boundary `region`. The contact condition
+       is prescribed with Nitsche's method. The rigid obstacle should
+       be described with the data `dataname_obstacle` being a signed distance to
+       the obstacle (interpolated on a finite element method).
+       `gamma0name` is the Nitsche's method parameter.
+       `theta` is a scalar value which can be
+       positive or negative. `theta = 1` corresponds to the standard symmetric
+       method which is conditionnaly coercive for  `gamma0` small.
+       `theta = -1` corresponds to the skew-symmetric method which is
+       inconditionnaly coercive. `theta = 0` is the simplest method
+       for which the second derivative of the Neumann term is not necessary.
+       The optional parameter `dataname_friction_coeff` is the friction
+       coefficient which could be constant or defined on a finite element
+       method.
+       CAUTION: This brick has to be added in the model after all the bricks
+       corresponding to partial differential terms having a Neumann term.
+       Moreover, This brick can only be applied to bricks declaring their
+       Neumann terms. Returns the brick index in the model.
+     @*/
+     sub_command
+       ("add Nitsche midpoint contact with rigid obstacle brick", 9, 10, 0, 1,
+        getfemint_mesh_im *gfi_mim = in.pop().to_getfemint_mesh_im();
+        std::string varname = in.pop().to_string();
+        std::string dataname_obs = in.pop().to_string();
+        std::string gamma0name = in.pop().to_string();
+        size_type region = in.pop().to_integer();
+ 
+        scalar_type theta = scalar_type(1);
+        std::string dataname_fr;
+        mexarg_in argin = in.pop();
+        if (argin.is_string())
+          dataname_fr = argin.to_string();
+        else
+          theta = argin.to_scalar();
+        dataname_fr = in.pop().to_string();
+        std::string dataname_alpha = in.pop().to_string();
+        std::string dataname_wt = in.pop().to_string();
+        size_type option = in.pop().to_integer();
+ 
+        size_type ind = config::base_index();
+        ind += getfem::add_Nitsche_midpoint_contact_with_rigid_obstacle_brick
+        (md->model(), gfi_mim->mesh_im(), varname, dataname_obs,
+ 	gamma0name, theta,
+ 	dataname_fr, dataname_alpha, dataname_wt, region, option);
+        workspace().set_dependance(md, gfi_mim);
+        out.pop().from_integer(int(ind));
+        );
+ 
+ #endif
+ 
+     /*@SET ind = ('add Nitsche fictitious domain contact brick', @tmim mim, @str varname1, @str varname2, @str dataname_d1, @str dataname_d2, @str gamma0name [, @scalar theta[, @str dataname_friction_coeff[, @str dataname_alpha, @str dataname_wt1, at str dataname_wt2]]])
+      Adds a contact condition with or without Coulomb friction between
+      two bodies in a fictitious domain. The contact condition is applied on 
+      the variable `varname_u1` corresponds with the first and slave body 
+      with Nitsche's method and on the variable `varname_u2` corresponds 
+      with the second and master body with Nitsche's method. 
+      The contact condition is evaluated on the fictitious slave boundary.
+      The first body should be described by the level-set `dataname_d1` 
+      and the second body should be described by the level-set `dataname_d2`.
+      `gamma0name` is the Nitsche's method parameter. 
+      `theta` is a scalar value which can be positive or negative. 
+      `theta = 1` corresponds to the standard symmetric method which is
+      conditionnaly coercive for  `gamma0` small.
+      `theta = -1` corresponds to the skew-symmetric method which is inconditionnaly coercive.
+      `theta = 0` is the simplest method for which the second derivative of
+      the Neumann term is not necessary. The optional parameter `dataname_friction_coeff`
+      is the friction coefficient which could be constant or defined on a finite element method. 
+      CAUTION: This brick has to be added in the model after all the bricks
+      corresponding to partial differential terms having a Neumann term.
+      Moreover, This brick can only be applied to bricks declaring their
+      Neumann terms. Returns the brick index in the model. 
+     @*/
+     sub_command
+       ("add Nitsche fictitious domain contact brick", 6, 11, 0, 1,
+        getfemint_mesh_im *gfi_mim = in.pop().to_getfemint_mesh_im();
+        std::string varname1 = in.pop().to_string();
+        std::string varname2 = in.pop().to_string();
+        std::string dataname_d1 = in.pop().to_string();
+        std::string dataname_d2 = in.pop().to_string();
+        std::string gamma0name = in.pop().to_string();
+ 
+        scalar_type theta = scalar_type(1);
+        std::string dataname_fr;
+        if (in.remaining()) {
+ 	 mexarg_in argin = in.pop();
+ 	 if (argin.is_string())
+ 	   dataname_fr = argin.to_string();
+ 	 else
+ 	   theta = argin.to_scalar();
+        }
+        if (in.remaining()) dataname_fr = in.pop().to_string();
+        std::string dataname_alpha;
+        if (in.remaining()) dataname_alpha = in.pop().to_string();
+        std::string dataname_wt1;
+        if (in.remaining()) dataname_wt1 = in.pop().to_string();
+        std::string dataname_wt2;
+        if (in.remaining()) dataname_wt2 = in.pop().to_string();
+ 
+        size_type ind = config::base_index();
+        ind += getfem::add_Nitsche_fictitious_domain_contact_brick
+        (md->model(), gfi_mim->mesh_im(), varname1, varname2, dataname_d1,
+         dataname_d2, gamma0name, theta,
+ 	dataname_fr, dataname_alpha, dataname_wt1, dataname_wt2);
+        workspace().set_dependance(md, gfi_mim);
+        out.pop().from_integer(int(ind));
+        );
++>>>>>>> upstream
  
      // CONTACT BETWEEN NON-MATCHING MESHES
  
@@@ -2302,7 -2636,37 +2732,41 @@@
          );
  
  
++<<<<<<< HEAD
 +     /*@SET ind = ('add integral large sliding contact brick',  @tmim mim, @str varname_u, @str multname, @str dataname_r, @str dataname_fr, @int rg)
++=======
+      /*@SET ind = ('add integral large sliding contact brick raytrace', @tmcf multi_contact, @str dataname_r[, @str dataname_fr[, @dataname_alpha]])
+       Adds a large sliding contact with friction brick to the model.
+       This brick is able to deal with self-contact, contact between
+       several deformable bodies and contact with rigid obstacles.
+       It takes a variable of type multi_contact_frame wich describe
+       the contact situation (master and slave contact boundaries,
+       self-contact detection or not, and a few parameter).
+       For each slave boundary (and also master boundaries if self-contact
+       is asked) a multiplier variable should be defined. @*/
+ 
+      sub_command
+        ("add integral large sliding contact brick raytrace", 2, 4, 0, 1,
+         
+         getfemint_multi_contact_frame *gfi_mcf
+           = in.pop().to_getfemint_multi_contact_frame();
+         std::string dataname_r = in.pop().to_string();
+         std::string dataname_fr;
+         if (in.remaining()) dataname_fr = in.pop().to_string();
+         std::string dataname_alpha;
+         if (in.remaining()) dataname_alpha = in.pop().to_string();
+ 
+         size_type  ind
+         = getfem::add_integral_large_sliding_contact_brick_raytrace
+         (md->model(), gfi_mcf->multi_contact_frame(), dataname_r,
+          dataname_fr, dataname_alpha);
+         out.pop().from_integer(int(ind + config::base_index()));
+         workspace().set_dependance(md, gfi_mcf);
+         );
+ 
+ 
+      /*@SET ind = ('add integral large sliding contact brick with field extension',  @tmim mim, @str varname_u, @str multname, @str dataname_r, @str dataname_fr, @int rg)
++>>>>>>> upstream
         (still experimental brick)
         Add a large sliding contact with friction brick to the model.
         This brick is able to deal with auto-contact, contact between
@@@ -2320,7 -2684,7 +2784,11 @@@
         `add_rigid_obstacle_to_large_sliding_contact_brick` to add contact
         boundaries and rigid obstacles. @*/
       sub_command
++<<<<<<< HEAD
 +       ("add integral large sliding contact brick", 6, 6, 0, 1,
++=======
+        ("add integral large sliding contact brick with field extension", 6, 6, 0, 1,
++>>>>>>> upstream
  
          getfemint_mesh_im *gfi_mim = in.pop().to_getfemint_mesh_im();
          std::string varname_u = in.pop().to_string();
@@@ -2329,7 -2693,7 +2797,11 @@@
          std::string dataname_fr = in.pop().to_string();
          size_type region = in.pop().to_integer();
          
++<<<<<<< HEAD
 +        size_type  ind = getfem::add_integral_large_sliding_contact_brick
++=======
+         size_type  ind = getfem::add_integral_large_sliding_contact_brick_field_extension
++>>>>>>> upstream
              (md->model(), gfi_mim->mesh_im(), varname_u, multname, dataname_r,
               dataname_fr, region);
          out.pop().from_integer(int(ind + config::base_index()));
diff --cc interface/src/gfi_array.h
index b22578d,33720ae..511896a
--- a/interface/src/gfi_array.h
+++ b/interface/src/gfi_array.h
@@@ -1,7 -1,7 +1,11 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
   
++<<<<<<< HEAD
 + Copyright (C) 2006-2012 Yves Renard, Julien Pommier.
++=======
+  Copyright (C) 2006-2013 Yves Renard, Julien Pommier.
++>>>>>>> upstream
   
   This file is a part of GETFEM++
   
diff --cc interface/src/python/getfem_python.c
index 6459191,2055735..4b5e58c
--- a/interface/src/python/getfem_python.c
+++ b/interface/src/python/getfem_python.c
@@@ -673,7 -673,7 +673,11 @@@ getfem_env(PyObject *self, PyObject *ar
      word_out = PyString_FromString("GetFEM++");
    }else if (strcmp(word_in,"copyright") == 0){
      word_out = PyString_FromString
++<<<<<<< HEAD
 +    ("2004-2012 Yves Renard, Julien Pommier");
++=======
+     ("2004-2013 Yves Renard, Julien Pommier");
++>>>>>>> upstream
    }else if (strcmp(word_in,"authors") == 0){
      word_out = PyString_FromString
      ("Yves Renard, Julien Pommier");
diff --cc interface/src/scilab/demos/demo_continuation.sce
index ac52b13,3adb26b..08c596c
--- a/interface/src/scilab/demos/demo_continuation.sce
+++ b/interface/src/scilab/demos/demo_continuation.sce
@@@ -1,5 -1,5 +1,9 @@@
  // Scilab GetFEM++ interface
++<<<<<<< HEAD
 +// Copyright (C) 2011-2011 Tomas Ligursky, Yves Renard.
++=======
+ // Copyright (C) 2011-2012 Tomas Ligursky, Yves Renard.
++>>>>>>> upstream
  //
  // This file is a part of GetFEM++
  //
@@@ -15,37 -15,43 +19,73 @@@
  // along  with  this program;  if not, write to the Free Software Foundation,
  // Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
  //
++<<<<<<< HEAD
 +// Simple example of the bifurcation problem: -Delta(u) + u = lambda exp(u)
++=======
+ // Simple example of the bifurcation problem: -Delta(u) + u = lambda * exp(u)
++>>>>>>> upstream
  //
  // This program is used to check that scilab-getfem is working. This is also
  // a good example of use of GetFEM++.
  //
  
++<<<<<<< HEAD
++=======
+ gf_workspace('clear all');
++>>>>>>> upstream
  lines(0);
  stacksize('max');
  
  if getos()=='Windows' then
    // Under Windows, all the trace messages are available in the dos console
++<<<<<<< HEAD
 +  // Under Linuxs, all the trace messages are redirected to the Scilab console
 +  consolebox('on');
 +end
 +gf_util('trace level',3);
 +gf_util('warning level',3);
 +
 +gf_workspace('clear all');
 +lambda = 0;
 +direction = 1;
 +nbstep = 80;
 +
 +maxit = 5;
 +thrit = 4;
 +minang = 0.993;
 +maxres_solve = 1.e-7;
 +noisy = 'very_noisy';
 +
 +h_init = 1e-3;
 +h_max = 2e-1;
 +h_min = 1e-5;
++=======
+   // Under Linux, all the trace messages are redirected to the Scilab console
+   consolebox('on');
+ end
+ gf_util('trace level', 1);
+ gf_util('warning level', 3);
+ 
+ // continuation data
+ datapath = get_absolute_file_path('demo_continuation.sce') + 'data/';
+ // If the file name bp_char is non-empty, the continuation will be started
+ // from the bifurcation point and the tangent with the index ind_tangent
+ // saved there, direction of that tangent will be determined by direction.
+ // Otherwise, the continuation will be initialised according to direction and
+ // lambda0.
+ bp_char = '';
+ //bp_char = 'continuation_step_62_bp.mat';
+ ind_tangent = 2;
+ direction = 1;
+ lambda0 = 0;
+ nbstep = 80;
+ 
+ h_init = 2e-2;
+ h_max = 2e-1;
+ h_min = 2e-5;
+ mincos = 0.997;
+ noisy = 'noisy';
++>>>>>>> upstream
  
  // create a simple cartesian mesh
  m = gf_mesh('cartesian', [0:.1:1]);
@@@ -62,27 -68,38 +102,62 @@@ mim = gf_mesh_im(m, 4)
  md = gf_model('real');
  gf_model_set(md, 'add fem variable', 'u', mf);
  gf_model_set(md, 'add Laplacian brick', mim, 'u');
++<<<<<<< HEAD
 +gf_model_set(md, 'add initialized data', 'lambda', [lambda]);
 +gf_model_set(md, 'add basic nonlinear brick', mim, 'u', 'u-lambda*exp(u)', '1-lambda*exp(u)', 'lambda');
 +
 +// initialise the continuation
 +scfac = 1 / gf_mesh_fem_get(mf, 'nbdof');
 +S = gf_cont_struct(md, 'lambda', scfac, 'max_iter', maxit, 'thr_iter', thrit, 'min_ang', minang, 'h_init', h_init, 'h_max', h_max, 'h_min', h_min, noisy);
 +
 +// compute an initial point
 +if (~isempty(noisy)) then
 +    printf('computing an initial point\n');
 +end
 +gf_model_get(md, 'solve', noisy, 'max_iter', 100, 'max_res', maxres_solve);
 +[T_U, T_lambda, h] = gf_cont_struct_get(S, 'init Moore-Penrose continuation', direction);
 +
 +U = gf_model_get(md, 'variable', 'u');
 +tau = gf_cont_struct_get(S, 'test function');
 +//printf('U = '); disp(U); printf('lambda = %e\n', lambda);
 +//printf('lambda - U(1) * exp(-U(1)) = %e\n', lambda - U(1) * exp(-U(1)));
 +
 +U_hist = zeros(1, nbstep + 1); lambda_hist = zeros(1, nbstep + 1);
 +U_hist(1) = U(1); lambda_hist(1) = lambda;
++=======
+ gf_model_set(md, 'add data', 'lambda', 1);
+ gf_model_set(md, 'add basic nonlinear brick', mim, 'u', ...
+              'u-lambda*exp(u)', '1-lambda*exp(u)', 'lambda');
+ 
+ // initialise the continuation
+ scfac = 1 / gf_mesh_fem_get(mf, 'nbdof');
+ S = gf_cont_struct(md, 'lambda', scfac, 'bifurcations', 'h_init', h_init, ...
+                    'h_max', h_max, 'h_min', h_min, 'min_cos', mincos, noisy);
+ 
+ if (~isempty(bp_char)) then
+   load(datapath + bp_char);
+   U = U_bp; lambda = lambda_bp;
+   T_U = direction * T_U_bp(:, ind_tangent);
+   T_lambda = direction * T_lambda_bp(ind_tangent);
+   h = gf_cont_struct_get(S, 'init step size');
+ else
+   lambda = lambda0;
+   gf_model_set(md, 'variable', 'lambda', [lambda]);
+   
+   if (~isempty(noisy)) then
+     printf('starting computing an initial point\n');
+   end
+   gf_model_get(md, 'solve', noisy, 'max_iter', 100);
+   U = gf_model_get(md, 'variable', 'u');
+   [T_U, T_lambda, h] = ...
+     gf_cont_struct_get(S, 'init Moore-Penrose continuation', ...
+                        U, lambda, direction);
+ end
+ 
+ U_hist = zeros(1, nbstep + 1); lambda_hist = zeros(1, nbstep + 1);
+ U_hist(1) = U(1); lambda_hist(1) = lambda;
+ //tau = gf_cont_struct_get(S, 'test function');
++>>>>>>> upstream
  
  scf(0); drawlater; clf();
  subplot(2,1,1);
@@@ -93,28 -110,33 +168,57 @@@ gf_plot_1D(mf, U, 'style', 'k.-')
  xtitle('', 'x', 'u');
  drawnow;
  
++<<<<<<< HEAD
 +scf(1); drawlater; clf();
 +plot(0, tau, 'k.');
 +xtitle('', 'iteration', 'tau');
 +drawnow;
 +
++=======
+ //scf(1); drawlater; clf();
+ //plot(0, tau, 'k.');
+ //xtitle('', 'iteration', 'test function');
+ //drawnow;
+ 
+ sing_out = [];
++>>>>>>> upstream
  // continue from the initial point
  for step = 1:nbstep
    //sleep(1000);
    printf('\nbeginning of step %d\n', step);
++<<<<<<< HEAD
 +  [T_U, T_lambda, h] = gf_cont_struct_get(S, 'Moore-Penrose continuation', T_U, T_lambda, h);
 +  if (h == 0) then
 +    printf('Continuation has failed');
 +    break;
 +  end
 +  
 +  U = gf_model_get(md, 'variable', 'u');
 +  lambda = gf_model_get(md, 'variable', 'lambda');
 +  tau = gf_cont_struct_get(S, 'test function');
 +  U_hist(step+1) = U(1); lambda_hist(step+1) = lambda;
 +//  printf('U = '); disp(U); printf('lambda = %e\n', lambda);
 +//  printf('lambda - U(1) * exp(-U(1)) = %e\n', lambda - U(1) * exp(-U(1)));
 +
++=======
+   [U, lambda, T_U, T_lambda, h, sing_label] = ...
+     gf_cont_struct_get(S, 'Moore-Penrose continuation',...
+                        U, lambda, T_U, T_lambda, h);
+   if (h == 0) then
+     return
+   elseif (sing_label == 'smooth bifurcation point') then
+      [U_bp, lambda_bp, T_U_bp, T_lambda_bp]...
+        = gf_cont_struct_get(S, 'sing_data');
+      save(datapath + 'continuation_step_' + sci2exp(step) + '_bp.mat',...
+        U_bp, lambda_bp, T_U_bp, T_lambda_bp);
+      s = 'step ' + sci2exp(step) + ': '...
+          + sci2exp(size(T_U_bp, 2)) + ' branch(es) located';
+      sing_out = [sing_out; s];
+   end
+   
+   U_hist(step+1) = U(1); lambda_hist(step+1) = lambda;
+ //  tau = gf_cont_struct_get(S, 'test function');
++>>>>>>> upstream
  
    scf(0); drawlater; clf();
    subplot(2,1,1);
@@@ -127,25 -149,19 +231,44 @@@
    xtitle('', 'x', 'u');
    drawnow;
  
++<<<<<<< HEAD
 +  scf(1); drawlater;
 +  plot(step, tau, 'k.');
 +  drawnow;
 +  
 +  // calculate the determinant of the augmented Jacobian directly
 +//  lambda = lambda + 1e-8; gf_model_set(md, 'variable', 'lambda', [lambda]);
 +//  gf_model_get(md, 'assembly', 'build_rhs');
 +//  F1 = gf_model_get(md, 'rhs');
 +//  lambda = lambda - 1e-8; gf_model_set(md, 'variable', 'lambda', [lambda]);
 +//  gf_model_get(md, 'assembly', 'build_all');
 +//  F0 = gf_model_get(md, 'rhs');
 +//  J(1:11,1:11) = gf_model_get(md, 'tangent_matrix');
 +//  J(1:11,12) = ((1 / 1e-8) * (F0 - F1))';
 +//  J(12,1:11) = T_U; J(12,12) = T_lambda; detJ = det(J);
 +//  printf('J = '); disp(J); printf('det(J) = %e\n', detJ);
 +//  scf(2); drawlater;
 +//  plot(step, detJ, 'k.');
 +//  xtitle('', 'iteration', 'tau');
 +//  drawnow;
 +  
 +  printf('end of step n° %d', step); printf(' / %d\n', nbstep);
- end
++end
++=======
+ //  scf(1); drawlater;
+ //  plot(step, tau, 'k.');
+ //  drawnow;
+   
+   printf('end of step n° %d / %d\n', step, nbstep)
+ end
+ 
+ nsing = size(sing_out, 1);
+ if (nsing > 0) then
+   printf('\n----------------------------------------------------------\n')
+   printf('   detected bifurcation points on the continuation curve\n')
+   printf('----------------------------------------------------------\n')
+   for i = 1:nsing
+     printf(sing_out(i) + '\n')
+   end
+ end
++>>>>>>> upstream
diff --cc interface/src/scilab/help/en_US/gf_asm.xml
index 6a56215,5e88d82..17a9f60
--- a/interface/src/scilab/help/en_US/gf_asm.xml
+++ b/interface/src/scilab/help/en_US/gf_asm.xml
@@@ -45,6 -45,7 +45,10 @@@
      <synopsis>Me = gf_asm('extrapolation matrix',mesh_fem mf, mesh_fem mfe)</synopsis>
      <synopsis>B = gf_asm('integral contact Uzawa projection', int bnum, mesh_im mim, mesh_fem mf_u, vec U, mesh_fem mf_lambda, vec vec_lambda, mesh_fem mf_obstacle, vec obstacle, scalar r [, {scalar coeff | mesh_fem mf_coeff, vec coeff} [, int option[, scalar alpha, vec W]]])</synopsis>
      <synopsis>B = gf_asm('level set normal source term', int bnum, mesh_im mim, mesh_fem mf_u, mesh_fem mf_lambda, vec vec_lambda, mesh_fem mf_levelset, vec levelset)</synopsis>
++<<<<<<< HEAD
++=======
+     <synopsis>B = gf_asm('Nitsche contact rigid obstacle rhs', int bnum, mesh_im mim, mesh_fem mf_u, vec U, mesh_fem mf_obs, vec obs, scalar fcoeff, scalar r, scalar theta, scalar clambda, scalar cmu)</synopsis>
++>>>>>>> upstream
    </refsynopsisdiv>
  
    <refsection>
@@@ -142,8 -143,13 +146,18 @@@
        Linearized law, should be avoided). This law has the two usual
        Lame coefficients as parameters, called lambda and mu.
        - 'Mooney Rivlin':
++<<<<<<< HEAD
 +      Only for incompressibility. This law has two parameters,
 +      called C1 and C2.
++=======
+       This law has three parameters, called C1, C2 and D1.
+       Can be preceded with the words 'compressible' or 'incompressible' to force
+       a specific version. By default, the incompressible version is considered
+       which requires only the first two material coefficients.
+       - 'neo Hookean':
+       A special case of the 'Mooney Rivlin' law that requires one material
+       coefficient less (C2 = 0). By default, its compressible version is used.
++>>>>>>> upstream
        - 'Ciarlet Geymonat':
        This law has 3 parameters, called lambda, mu and gamma, with
        gamma chosen such that gamma is in ]-lambda/2-mu, -mu[.
@@@ -355,7 -361,7 +369,11 @@@
      </listitem>
  
      <listitem>
++<<<<<<< HEAD
 +    <para><literal>B = gf_asm('contact with friction Uzawa projection', int bnum, mesh_im mim, mesh_fem mf_u, vec U, mesh_fem mf_lambda, vec vec_lambda, mesh_fem mf_obstacle, vec obstacle, scalar r [, {scalar coeff | mesh_fem mf_coeff, vec coeff} [, int option[, scalar alpha, vec W]]])</literal></para>
++=======
+     <para><literal>B = gf_asm('integral contact Uzawa projection', int bnum, mesh_im mim, mesh_fem mf_u, vec U, mesh_fem mf_lambda, vec vec_lambda, mesh_fem mf_obstacle, vec obstacle, scalar r [, {scalar coeff | mesh_fem mf_coeff, vec coeff} [, int option[, scalar alpha, vec W]]])</literal></para>
++>>>>>>> upstream
  
      <para>       Specific assembly procedure for the use of an Uzawa algorithm to solve
        contact problems. Projects the term $-(\lambda - r (u_N-g))_-$ on the
@@@ -379,6 -385,17 +397,20 @@@
      </para>
      </listitem>
  
++<<<<<<< HEAD
++=======
+     <listitem>
+     <para><literal>B = gf_asm('Nitsche contact rigid obstacle rhs', int bnum, mesh_im mim, mesh_fem mf_u, vec U, mesh_fem mf_obs, vec obs, scalar fcoeff, scalar r, scalar theta, scalar clambda, scalar cmu)</literal></para>
+ 
+     <para>       Compute the right hand side (residual) of the Nitsche term for contact
+     with friction on a rigid obstacle of a linearly elastic body. Experimental.
+ 
+     Return a vec object.
+     
+     </para>
+     </listitem>
+ 
++>>>>>>> upstream
      </itemizedlist>
    </refsection>
  
diff --cc interface/src/scilab/help/en_US/gf_mdbrick.xml
index cc479fa,a724e4a..c1b72b7
--- a/interface/src/scilab/help/en_US/gf_mdbrick.xml
+++ b/interface/src/scilab/help/en_US/gf_mdbrick.xml
@@@ -227,7 -227,13 +227,17 @@@
      - 'SaintVenant Kirchhoff' :
        Linearized material law.
      - 'Mooney Rivlin' :
++<<<<<<< HEAD
 +      To be used with the nonlinear incompressibily term.
++=======
+       Can be preceded with the words 'compressible' or 'incompressible' to force
+       a specific version. By default, the incompressible version is considered,
+       which has to be used with the nonlinear incompressibily term.
+       The compressible version requires one additional material coefficient.
+     - 'neo Hookean' :
+       A special case of the 'Mooney Rivlin' law that requires one material
+       coefficient less. By default, its compressible version is used.
++>>>>>>> upstream
      - 'Ciarlet Geymonat'
      </para>
      </listitem>
diff --cc interface/src/scilab/help/en_US/gf_model_get.xml
index 46395dc,745650f..451f0e8
--- a/interface/src/scilab/help/en_US/gf_model_get.xml
+++ b/interface/src/scilab/help/en_US/gf_model_get.xml
@@@ -25,7 -25,7 +25,11 @@@
      <synopsis>gf_model_get(model M, 'listvar')</synopsis>
      <synopsis>gf_model_get(model M, 'listbricks')</synopsis>
      <synopsis>V = gf_model_get(model M, 'variable', string name[, int niter])</synopsis>
++<<<<<<< HEAD
 +    <synopsis>V = gf_model_get(model M, 'mesh fem of variable', string name)</synopsis>
++=======
+     <synopsis>mf = gf_model_get(model M, 'mesh fem of variable', string name)</synopsis>
++>>>>>>> upstream
      <synopsis>name = gf_model_get(model M, 'mult varname Dirichlet', int ind_brick)</synopsis>
      <synopsis>I = gf_model_get(model M, 'interval of variable', string varname)</synopsis>
      <synopsis>V = gf_model_get(model M, 'from variables')</synopsis>
@@@ -127,7 -127,7 +131,11 @@@
      </listitem>
  
      <listitem>
++<<<<<<< HEAD
 +    <para><literal>V = gf_model_get(model M, 'mesh fem of variable', string name)</literal></para>
++=======
+     <para><literal>mf = gf_model_get(model M, 'mesh fem of variable', string name)</literal></para>
++>>>>>>> upstream
  
      <para>         Gives access to the <literal>mesh_fem</literal> of a variable or data.
      </para>
@@@ -247,7 -247,7 +255,11 @@@
  
      <para>         Compute on <literal>mf_vm</literal> the Von-Mises stress or the Tresca stress of a field
        for nonlinear elasticity in 3D. <literal>lawname</literal> is the constitutive law which
++<<<<<<< HEAD
 +      could be 'SaintVenant Kirchhoff', 'Mooney Rivlin' or 'Ciarlet Geymonat'.
++=======
+       could be 'SaintVenant Kirchhoff', 'Mooney Rivlin', 'neo Hookean' or 'Ciarlet Geymonat'.
++>>>>>>> upstream
        <literal>dataname</literal> is a vector of parameters for the constitutive law. Its length
        depends on the law. It could be a short vector of constant values or a
        vector field described on a finite element method for variable coefficients.
@@@ -260,7 -260,7 +272,11 @@@
  
      <para>         Compute on <literal>mf_sigma</literal> the second Piola Kirchhoff stress tensor of a field
        for nonlinear elasticity in 3D. <literal>lawname</literal> is the constitutive law which
++<<<<<<< HEAD
 +      could be 'SaintVenant Kirchhoff', 'Mooney Rivlin' or 'Ciarlet Geymonat'.
++=======
+       could be 'SaintVenant Kirchhoff', 'Mooney Rivlin', 'neo Hookean' or 'Ciarlet Geymonat'.
++>>>>>>> upstream
        <literal>dataname</literal> is a vector of parameters for the constitutive law. Its length
        depends on the law. It could be a short vector of constant values or a
        vector field described on a finite element method for variable
diff --cc interface/src/scilab/help/en_US/gf_model_set.xml
index 560c618,e3638d8..1d203cf
--- a/interface/src/scilab/help/en_US/gf_model_set.xml
+++ b/interface/src/scilab/help/en_US/gf_model_set.xml
@@@ -18,9 -18,10 +18,16 @@@
  
      <synopsis>gf_model_set(model M, 'clear')</synopsis>
      <synopsis>gf_model_set(model M, 'add fem variable', string name, mesh_fem mf[, int niter])</synopsis>
++<<<<<<< HEAD
 +    <synopsis>gf_model_set(model M, 'add variable', string name, int size[, int niter])</synopsis>
 +    <synopsis>gf_model_set(model M, 'resize variable', string name, int size)</synopsis>
 +    <synopsis>gf_model_set(model M, 'add multiplier', string name, mesh_fem mf, string primalname[, int niter])</synopsis>
++=======
+     <synopsis>gf_model_set(model M, 'add filtered fem variable', string name, mesh_fem mf, int region[, int niter])</synopsis>
+     <synopsis>gf_model_set(model M, 'add variable', string name, int size[, int niter])</synopsis>
+     <synopsis>gf_model_set(model M, 'resize variable', string name, int size)</synopsis>
+     <synopsis>gf_model_set(model M, 'add multiplier', string name, mesh_fem mf, string primalname[, mesh_im mim, int region][, int niter])</synopsis>
++>>>>>>> upstream
      <synopsis>gf_model_set(model M, 'add fem data', string name, mesh_fem mf[, int qdim[, int niter]])</synopsis>
      <synopsis>gf_model_set(model M, 'add initialized fem data', string name, mesh_fem mf, vec V)</synopsis>
      <synopsis>gf_model_set(model M, 'add data', string name, int size[, int niter])</synopsis>
@@@ -78,10 -79,14 +85,21 @@@
      <synopsis>gf_model_set(model M, 'contact brick set BN', int indbrick, spmat BN)</synopsis>
      <synopsis>gf_model_set(model M, 'contact brick set BT', int indbrick, spmat BT)</synopsis>
      <synopsis>ind = gf_model_set(model M, 'add nodal contact with rigid obstacle brick',  mesh_im mim, string varname_u, string multname_n[, string multname_t], string dataname_r[, string dataname_friction_coeff], int region, string obstacle[,  int augmented_version])</synopsis>
++<<<<<<< HEAD
 +    <synopsis>ind = gf_model_set(model M, 'add integral contact with rigid obstacle brick',  mesh_im mim, string varname_u, string multname, string dataname_obstacle, string dataname_r [, string dataname_friction_coeff], int region [, int option [, string dataname_alpha [, string dataname_wt [, string dataname_gamma [, string dataname_vt]]]]])</synopsis>
 +    <synopsis>ind = gf_model_set(model M, 'add penalized contact with rigid obstacle brick',  mesh_im mim, string varname_u, string dataname_obstacle, string dataname_r [, string dataname_coeff], int region [, int option, string dataname_lambda, [, string dataname_alpha [, string dataname_wt]]])</synopsis>
 +    <synopsis>ind = gf_model_set(model M, 'add Nitsche contact with rigid obstacle brick',  mesh_im mim, string varname_u, string dataname_obstacle, string dataname_r, string dataname_friction_coeff, string dataname_lambda, string dataname_mu, int region)</synopsis>
 +    <synopsis>ind = gf_model_set(model M, 'add nodal contact between nonmatching meshes brick',  mesh_im mim1[, mesh_im mim2], string varname_u1[, string varname_u2], string multname_n[, string multname_t], string dataname_r[, string dataname_fr], int rg1, int rg2[, int slave1, int slave2,  int augmented_version])</synopsis>
++=======
+     <synopsis>ind = gf_model_set(model M, 'add contact with rigid obstacle brick',  mesh_im mim, string varname_u, string multname_n[, string multname_t], string dataname_r[, string dataname_friction_coeff], int region, string obstacle[,  int augmented_version])</synopsis>
+     <synopsis>ind = gf_model_set(model M, 'add integral contact with rigid obstacle brick',  mesh_im mim, string varname_u, string multname, string dataname_obstacle, string dataname_r [, string dataname_friction_coeff], int region [, int option [, string dataname_alpha [, string dataname_wt [, string dataname_gamma [, string dataname_vt]]]]])</synopsis>
+     <synopsis>ind = gf_model_set(model M, 'add penalized contact with rigid obstacle brick',  mesh_im mim, string varname_u, string dataname_obstacle, string dataname_r [, string dataname_coeff], int region [, int option, string dataname_lambda, [, string dataname_alpha [, string dataname_wt]]])</synopsis>
+     <synopsis>ind = gf_model_set(model M, 'add Nitsche contact with rigid obstacle brick',  mesh_im mim, string varname_u, string dataname_obstacle, string dataname_r, string dataname_theta, string dataname_friction_coeff, string dataname_lambda, string dataname_mu, int region)</synopsis>
+     <synopsis>ind = gf_model_set(model M, 'add nodal contact between nonmatching meshes brick',  mesh_im mim1[, mesh_im mim2], string varname_u1[, string varname_u2], string multname_n[, string multname_t], string dataname_r[, string dataname_fr], int rg1, int rg2[, int slave1, int slave2,  int augmented_version])</synopsis>
+     <synopsis>ind = gf_model_set(model M, 'add nonmatching meshes contact brick',  mesh_im mim1[, mesh_im mim2], string varname_u1[, string varname_u2], string multname_n[, string multname_t], string dataname_r[, string dataname_fr], int rg1, int rg2[, int slave1, int slave2,  int augmented_version])</synopsis>
+     <synopsis>ind = gf_model_set(model M, 'add integral contact between nonmatching meshes brick',  mesh_im mim, string varname_u1, string varname_u2, string multname, string dataname_r [, string dataname_friction_coeff], int region1, int region2 [, int option [, string dataname_alpha [, string dataname_wt1 , string dataname_wt2]]])</synopsis>
+     <synopsis>ind = gf_model_set(model M, 'add penalized contact between nonmatching meshes brick',  mesh_im mim, string varname_u1, string varname_u2, string dataname_r [, string dataname_coeff], int region1, int region2 [, int option [, string dataname_lambda, [, string dataname_alpha [, string dataname_wt1, string dataname_wt2]]]])</synopsis>
++>>>>>>> upstream
      <synopsis>ind = gf_model_set(model M, 'add integral large sliding contact brick',  mesh_im mim, string varname_u, string multname, string dataname_r, string dataname_fr, int rg)</synopsis>
      <synopsis>ind = gf_model_set(model M, 'add boundary to large sliding contact brick',  int indbrick, mesh_im mim, string varname_u, string multname, int rg)</synopsis>
      <synopsis>ind = gf_model_set(model M, 'add rigid obstacle to large sliding contact brick',  int indbrick, string obs)</synopsis>
@@@ -114,6 -119,16 +132,19 @@@
      </listitem>
  
      <listitem>
++<<<<<<< HEAD
++=======
+     <para><literal>gf_model_set(model M, 'add filtered fem variable', string name, mesh_fem mf, int region[, int niter])</literal></para>
+ 
+     <para>         Add a variable to the model linked to a mesh_fem. The variable is filtered
+       in the sense that only the dof on the region are considered.
+       <literal>name</literal> is the variable name and <literal>niter</literal> is the optional number of
+       version of the data stored, for time integration schemes.
+     </para>
+     </listitem>
+ 
+     <listitem>
++>>>>>>> upstream
      <para><literal>gf_model_set(model M, 'add variable', string name, int size[, int niter])</literal></para>
  
      <para>         Add a variable to the model of constant size. <literal>name</literal> is the variable
@@@ -131,7 -146,7 +162,11 @@@
      </listitem>
  
      <listitem>
++<<<<<<< HEAD
 +    <para><literal>gf_model_set(model M, 'add multiplier', string name, mesh_fem mf, string primalname[, int niter])</literal></para>
++=======
+     <para><literal>gf_model_set(model M, 'add multiplier', string name, mesh_fem mf, string primalname[, mesh_im mim, int region][, int niter])</literal></para>
++>>>>>>> upstream
  
      <para>       Add a particular variable linked to a fem being a multiplier with
      respect to a primal variable. The dof will be filtered with the
@@@ -606,8 -621,15 +641,20 @@@
  
      <para>       Add a nonlinear elasticity term to the model relatively to the
      variable <literal>varname</literal>. <literal>lawname</literal> is the constitutive law which
++<<<<<<< HEAD
 +    could be 'SaintVenant Kirchhoff', 'Mooney Rivlin', 'Ciarlet Geymonat'
 +    or 'generalized Blatz Ko'.
++=======
+     could be 'SaintVenant Kirchhoff', 'Mooney Rivlin', 'neo Hookean',
+     'Ciarlet Geymonat' or 'generalized Blatz Ko'.
+     'Mooney Rivlin' and 'neo Hookean' law names can be preceded with the word
+     'compressible' or 'incompressible' to force using the corresponding version.
+     The compressible version of these laws requires one additional material
+     coefficient. By default, the incompressible version of 'Mooney Rivlin' law
+     and the compressible one of the 'neo Hookean' law are considered. In general,
+     'neo Hookean' is a special case of the 'Mooney Rivlin' law that requires one
+     coefficient less.
++>>>>>>> upstream
      IMPORTANT : if the variable is defined on a 2D mesh, the plane strain
      approximation is automatically used.
      <literal>dataname</literal> is a vector of parameters for the constitutive law. Its length
@@@ -628,7 -650,7 +675,11 @@@
        we want to use. For the moment, only the Von Mises projection is
        computing that we could entering 'VM' or 'Von Mises'.
        <literal>datasigma</literal> is the variable representing the constraints on the material.
++<<<<<<< HEAD
 +      Be carefull that <literal>varname</literal> and <literal>datasigma</literal> are composed of two iterates
++=======
+       Be careful that <literal>varname</literal> and <literal>datasigma</literal> are composed of two iterates
++>>>>>>> upstream
        for the time scheme needed for the Newton algorithm used.
        Moreover, the finite element method on which <literal>varname</literal> is described
        is an K ordered mesh_fem, the <literal>datasigma</literal> one have to be at least
@@@ -914,9 -936,9 +965,15 @@@
       (see Getfem user documentation).  The parameter <literal>augmented_version</literal>
       indicates the augmentation strategy : 1 for the non-symmetric
       Alart-Curnier augmented Lagrangian, 2 for the symmetric one (except for
++<<<<<<< HEAD
 +     the coupling between contact and Coulomb friction), 3 for the symmetric
 +     one with an additional term, 4 for the new unsymmetric method,
 +     5 for the new unsymmetric method with De Saxce projection. 
++=======
+      the coupling between contact and Coulomb friction), 3 for the
+      unsymmetric method with augmented multipliers, 4 for the unsymmetric
+      method with augmented multipliers and De Saxce projection. 
++>>>>>>> upstream
      </para>
      </listitem>
  
@@@ -970,61 -992,68 +1027,123 @@@
      </listitem>
  
      <listitem>
++<<<<<<< HEAD
 +    <para><literal>ind = gf_model_set(model M, 'add integral contact with rigid obstacle brick',  mesh_im mim, string varname_u, string multname, string dataname_obstacle, string dataname_r [, string dataname_friction_coeff], int region [, int option [, string dataname_alpha [, string dataname_wt [, string dataname_gamma [, string dataname_vt]]]]])</literal></para>
 +
 +    <para>   
 +      Add a contact with or without friction condition with a rigid obstacle
 +      to the model. This brick adds a contact which is defined
 +      in an integral way. It is the direct approximation of an augmented
 +      Lagrangian formulation (see Getfem user documentation) defined at the
 +      continuous level. The advantage should be a better scalability:
 +      the number of the
 +      Newton iterations should be more or less independent of the mesh size.
 +      The condition is applied on the variable <literal>varname_u</literal>
 +      on the boundary corresponding to <literal>region</literal>. The rigid obstacle should
 +      be described with the data <literal>dataname_obstacle</literal> being a signed distance
 +      to the obstacle (interpolated on a finite element method).
 +      <literal>multname</literal> should be a fem variable representing the contact stress.
 +      An inf-sup condition between <literal>multname</literal> and <literal>varname_u</literal> is required.
 +      The augmentation parameter <literal>dataname_r</literal> should be chosen in a
 +      range of acceptable values. <literal>dataname_friction_coeff</literal> is the friction
 +      coefficient which could be constant or defined on a finite element
 +      method.
 +      Possible values for <literal>option</literal> is 1 for the non-symmetric Alart-Curnier
 +      augmented Lagrangian method, 2 for the symmetric one, 3 for the
 +      non-symmetric Alart-Curnier method with an additional augmentation
 +      and 4 for a new unsymmetric method. The default value is 1.
 +      <literal>dataname_alpha</literal> and <literal>dataname_wt</literal> are optional parameters to solve
 +      evolutionary friction problems. <literal>dataname_gamma</literal> and <literal>dataname_vt</literal>
 +      represent optional data for adding a parameter-dependent sliding
 +      velocity to the friction condition.
++=======
+     <para><literal>ind = gf_model_set(model M, 'add contact with rigid obstacle brick',  mesh_im mim, string varname_u, string multname_n[, string multname_t], string dataname_r[, string dataname_friction_coeff], int region, string obstacle[,  int augmented_version])</literal></para>
+ 
+     <para>       DEPRECATED FUNCTION. Use 'add nodal contact with rigid obstacle brick' instead.
+     </para>
+     </listitem>
+ 
+     <listitem>
+     <para><literal>ind = gf_model_set(model M, 'add integral contact with rigid obstacle brick',  mesh_im mim, string varname_u, string multname, string dataname_obstacle, string dataname_r [, string dataname_friction_coeff], int region [, int option [, string dataname_alpha [, string dataname_wt [, string dataname_gamma [, string dataname_vt]]]]])</literal></para>
+ 
+     <para>   
+     Add a contact with or without friction condition with a rigid obstacle
+     to the model. This brick adds a contact which is defined
+     in an integral way. It is the direct approximation of an augmented
+     Lagrangian formulation (see Getfem user documentation) defined at the
+     continuous level. The advantage is a better scalability: the number of
+     Newton iterations should be more or less independent of the mesh size.
+     The contact condition is applied on the variable <literal>varname_u</literal>
+     on the boundary corresponding to <literal>region</literal>. The rigid obstacle should
+     be described with the data <literal>dataname_obstacle</literal> being a signed distance to
+     the obstacle (interpolated on a finite element method).
+     <literal>multname</literal> should be a fem variable representing the contact stress.
+     An inf-sup condition beetween <literal>multname</literal> and <literal>varname_u</literal> is required.
+     The augmentation parameter <literal>dataname_r</literal> should be chosen in a
+     range of acceptabe values.
+     The optional parameter <literal>dataname_friction_coeff</literal> is the friction
+     coefficient which could be constant or defined on a finite element method.
+     Possible values for <literal>option</literal> is 1 for the non-symmetric Alart-Curnier
+     augmented Lagrangian method, 2 for the symmetric one, 3 for the
+     non-symmetric Alart-Curnier method with an additional augmentation
+     and 4 for a new unsymmetric method. The default value is 1.
+     In case of contact with friction, <literal>dataname_alpha</literal> and <literal>dataname_wt</literal>
+     are optional parameters to solve evolutionary friction problems.
+     <literal>dataname_gamma</literal> and <literal>dataname_vt</literal> represent optional data for adding
+     a parameter-dependent sliding velocity to the friction condition.
++>>>>>>> upstream
      
      </para>
      </listitem>
  
      <listitem>
++<<<<<<< HEAD
 +    <para><literal>ind = gf_model_set(model M, 'add penalized contact with rigid obstacle brick',  mesh_im mim, string varname_u, string dataname_obstacle, string dataname_r [, string dataname_coeff,] int region [, int option, string dataname_lambda, [, string dataname_alpha [, string dataname_wt]]])</literal></para>
 +
 +    <para>
 +      Adds a penalized contact with or without friction condition with a
 +      rigid obstacle to the model.
 +      The condition is applied on the variable <literal>varname_u</literal>
 +      on the boundary corresponding to <literal>region</literal>. The rigid obstacle should
 +      be described with the data <literal>dataname_obstacle</literal> being a signed distance to
 +      the obstacle (interpolated on a finite element method).
 +      The penalization parameter <literal>dataname_r</literal> should be chosen
 +      large enough to prescribe approximate non-penetration and friction
 +      conditions but not too large not to deteriorate too much the
 +      conditionning of the tangent system.
 +      <literal>dataname_lambda</literal> is an optional parameter used if option
 +      is 2. In that case, the penalization term is shifted by lambda (this
 +      allows the use of an Uzawa algorithm on the corresponding augmented
 +      Lagrangian formulation)
++=======
+     <para><literal>ind = gf_model_set(model M, 'add penalized contact with rigid obstacle brick',  mesh_im mim, string varname_u, string dataname_obstacle, string dataname_r [, string dataname_coeff], int region [, int option, string dataname_lambda, [, string dataname_alpha [, string dataname_wt]]])</literal></para>
+ 
+     <para>   
+     Add a penalized contact with or without friction condition with a
+     rigid obstacle to the model.
+     The condition is applied on the variable <literal>varname_u</literal>
+     on the boundary corresponding to <literal>region</literal>. The rigid obstacle should
+     be described with the data <literal>dataname_obstacle</literal> being a signed distance to
+     the obstacle (interpolated on a finite element method).
+     The penalization parameter <literal>dataname_r</literal> should be chosen
+     large enough to prescribe approximate non-penetration and friction
+     conditions but not too large not to deteriorate too much the
+     conditionning of the tangent system.
+     <literal>dataname_lambda</literal> is an optional parameter used if option
+     is 2. In that case, the penalization term is shifted by lambda (this
+     allows the use of an Uzawa algorithm on the corresponding augmented
+     Lagrangian formulation)
+     
++>>>>>>> upstream
      </para>
      </listitem>
  
      <listitem>
++<<<<<<< HEAD
 +    <para><literal>ind = gf_model_set(model M, 'add Nitsche contact with rigid obstacle brick',  mesh_im mim, string varname_u, string dataname_obstacle, string dataname_r, string dataname_friction_coeff, string dataname_lambda, string dataname_mu, int region)</literal></para>
++=======
+     <para><literal>ind = gf_model_set(model M, 'add Nitsche contact with rigid obstacle brick',  mesh_im mim, string varname_u, string dataname_obstacle, string dataname_r, string dataname_theta, string dataname_friction_coeff, string dataname_lambda, string dataname_mu, int region)</literal></para>
++>>>>>>> upstream
  
      <para>   
        Add a contact with friction condition with a rigid obstacle
@@@ -1036,7 -1065,10 +1155,14 @@@
        be described with the data <literal>dataname_obstacle</literal> being a signed distance
        to the obstacle (interpolated on a finite element method).
        The Nitsche parameter <literal>dataname_r</literal> should be chosen in a
++<<<<<<< HEAD
 +      range of acceptable values. <literal>dataname_friction_coeff</literal> is the friction
++=======
+       range of acceptable values. <literal>dataname_theta</literal> corresponds to the real
+       parameter (1 for the classical symmetric version, 0 for the simplest
+       non symmetric one, -1 for the classical unconditionally coercive
+       non-symmetric one). <literal>dataname_friction_coeff</literal> is the friction
++>>>>>>> upstream
        coefficient which could be constant or defined on a finite element
        method. <literal>dataname_lambda</literal> and <literal>dataname_mu</literal> are the Lame coefficients.
      
@@@ -1081,6 -1113,72 +1207,75 @@@
      </listitem>
  
      <listitem>
++<<<<<<< HEAD
++=======
+     <para><literal>ind = gf_model_set(model M, 'add nonmatching meshes contact brick',  mesh_im mim1[, mesh_im mim2], string varname_u1[, string varname_u2], string multname_n[, string multname_t], string dataname_r[, string dataname_fr], int rg1, int rg2[, int slave1, int slave2,  int augmented_version])</literal></para>
+ 
+     <para>       DEPRECATED FUNCTION. Use 'add nodal contact between nonmatching meshes brick' instead.
+     </para>
+     </listitem>
+ 
+     <listitem>
+     <para><literal>ind = gf_model_set(model M, 'add integral contact between nonmatching meshes brick',  mesh_im mim, string varname_u1, string varname_u2, string multname, string dataname_r [, string dataname_friction_coeff], int region1, int region2 [, int option [, string dataname_alpha [, string dataname_wt1 , string dataname_wt2]]])</literal></para>
+ 
+     <para>   
+     Add a contact with or without friction condition between nonmatching
+     meshes to the model. This brick adds a contact which is defined
+     in an integral way. It is the direct approximation of an augmented
+     agrangian formulation (see Getfem user documentation) defined at the
+     continuous level. The advantage should be a better scalability:
+     the number of Newton iterations should be more or less independent
+     of the mesh size.
+     The condition is applied on the variables <literal>varname_u1</literal> and <literal>varname_u2</literal>
+     on the boundaries corresponding to <literal>region1</literal> and <literal>region2</literal>.
+     <literal>multname</literal> should be a fem variable representing the contact stress
+     for the frictionless case and the contact and friction stress for the
+     case with friction. An inf-sup condition between <literal>multname</literal> and
+     <literal>varname_u1</literal> and <literal>varname_u2</literal> is required.
+     The augmentation parameter <literal>dataname_r</literal> should be chosen in a
+     range of acceptable values.
+     The optional parameter <literal>dataname_friction_coeff</literal> is the friction
+     coefficient which could be constant or defined on a finite element
+     method on the same mesh as <literal>varname_u1</literal>.
+     Possible values for <literal>option</literal> is 1 for the non-symmetric Alart-Curnier
+     augmented Lagrangian method, 2 for the symmetric one, 3 for the
+     non-symmetric Alart-Curnier method with an additional augmentation
+     and 4 for a new unsymmetric method. The default value is 1.
+     In case of contact with friction, <literal>dataname_alpha</literal>, <literal>dataname_wt1</literal> and
+     <literal>dataname_wt2</literal> are optional parameters to solve evolutionary friction
+     problems.
+     
+     </para>
+     </listitem>
+ 
+     <listitem>
+     <para><literal>ind = gf_model_set(model M, 'add penalized contact between nonmatching meshes brick',  mesh_im mim, string varname_u1, string varname_u2, string dataname_r [, string dataname_coeff], int region1, int region2 [, int option [, string dataname_lambda, [, string dataname_alpha [, string dataname_wt1, string dataname_wt2]]]])</literal></para>
+ 
+     <para>   
+     Add a penalized contact condition with or without friction between
+     nonmatching meshes to the model.
+     The condition is applied on the variables <literal>varname_u1</literal> and  <literal>varname_u2</literal>
+     on the boundaries corresponding to <literal>region1</literal> and <literal>region2</literal>.
+     The penalization parameter <literal>dataname_r</literal> should be chosen
+     large enough to prescribe approximate non-penetration and friction
+     conditions but not too large not to deteriorate too much the
+     conditionning of the tangent system.
+     The optional parameter <literal>dataname_friction_coeff</literal> is the friction
+     coefficient which could be constant or defined on a finite element
+     method on the same mesh as <literal>varname_u1</literal>.
+     <literal>dataname_lambda</literal> is an optional parameter used if option
+     is 2. In that case, the penalization term is shifted by lambda (this
+     allows the use of an Uzawa algorithm on the corresponding augmented
+     Lagrangian formulation)
+     In case of contact with friction, <literal>dataname_alpha</literal>, <literal>dataname_wt1</literal> and
+     <literal>dataname_wt2</literal> are optional parameters to solve evolutionary friction
+     problems.
+     
+     </para>
+     </listitem>
+ 
+     <listitem>
++>>>>>>> upstream
      <para><literal>ind = gf_model_set(model M, 'add integral large sliding contact brick',  mesh_im mim, string varname_u, string multname, string dataname_r, string dataname_fr, int rg)</literal></para>
  
      <para>          (still experimental brick)
diff --cc interface/src/scilab/macros/gf_plot_mesh.sci
index 5816f70,c3fbcde..084b2e2
--- a/interface/src/scilab/macros/gf_plot_mesh.sci
+++ b/interface/src/scilab/macros/gf_plot_mesh.sci
@@@ -153,7 -153,7 +153,11 @@@ if (mdim > 3) then error('sorry, only m
        plot(X, Y);
        hmesh = gce();
        hmesh.children(:).thickness  = o_edges_width;
++<<<<<<< HEAD
 +      hmesh.children(:).line_style = 0; // Continous lines
++=======
+       hmesh.children(:).line_style = 1; // Continous lines
++>>>>>>> upstream
        hmesh.children(:).foreground = color(round(255*o_edges_color(1)),round(255*o_edges_color(2)),round(255*o_edges_color(3)));
        drawnow;
      end
@@@ -197,7 -197,7 +201,11 @@@
        plot3d(X, Y, Z); // 'Color',o_edges_color,'LineWidth',o_edges_width
        hmesh = gce();
        hmesh.thickness  = o_edges_width;
++<<<<<<< HEAD
 +      //hmesh.children(:).line_style = 0; // Continuous line
++=======
+       //hmesh.children(:).line_style = 1; // Continuous line
++>>>>>>> upstream
        hmesh.foreground = color(round(255*o_edges_color(1)),round(255*o_edges_color(2)),round(255*o_edges_color(3)));
        drawnow;
      end
@@@ -206,7 -206,7 +214,11 @@@
        plot3d(bedge(bnum)(:,:,1), bedge(bnum)(:,:,2), bedge(bnum)(:,:,3)); // 'Color','red','LineWidth',2);
        hbound(bnum) = gce();
        hbound(bnum).thickness  = 2;
++<<<<<<< HEAD
 +      hbound(bnum).line_style = 0; // Continuous line
++=======
+       hbound(bnum).line_style = 1; // Continuous line
++>>>>>>> upstream
        hbound(bnum).foreground = 5; // Red
        drawnow;
      end
diff --cc interface/src/scilab/macros/overload/%objid_e.sci
index d4b3176,8cb2ed2..9981ec2
--- a/interface/src/scilab/macros/overload/%objid_e.sci
+++ b/interface/src/scilab/macros/overload/%objid_e.sci
@@@ -56,15 -56,18 +56,30 @@@ function varargout = %objid_e(varargin
      // gfModel
      varargout = gf_model_get(gf_obj,other_param);
    case 16 then
++<<<<<<< HEAD
 +    // gfPrecond
 +    varargout = gf_precond_get(gf_obj,other_param);
 +  case 17 then
 +    // gfSlice
 +    varargout = gf_slice_get(gf_obj,other_param);
 +  case 18 then
 +    // gfSpmat
 +    varargout = gf_spmat_get(gf_obj,other_param);
 +  case 19 then
++=======
+     // gfMultiContactFrame
+     varargout = gf_multi_contact_frame_get(gf_obj,other_param);
+   case 17 then
+     // gfPrecond
+     varargout = gf_precond_get(gf_obj,other_param);
+   case 18 then
+     // gfSlice
+     varargout = gf_slice_get(gf_obj,other_param);
+   case 19 then
+     // gfSpmat
+     varargout = gf_spmat_get(gf_obj,other_param);
+   case 20 then
++>>>>>>> upstream
      // gfPoly
      // No gf_poly_get function
    else
diff --cc interface/src/scilab/macros/overload/%objid_get.sci
index b2e8bfc,f6cb590..5db29ec
--- a/interface/src/scilab/macros/overload/%objid_get.sci
+++ b/interface/src/scilab/macros/overload/%objid_get.sci
@@@ -56,15 -56,18 +56,30 @@@ function varargout = %objid_get(varargi
      // gfModel
      varargout = gf_model_get(gf_obj,other_param(:));
    case 16 then
++<<<<<<< HEAD
 +    // gfPrecond
 +    varargout = gf_precond_get(gf_obj,other_param(:));
 +  case 17 then
 +    // gfSlice
 +    varargout = gf_slice_get(gf_obj,other_param(:));
 +  case 18 then
 +    // gfSpmat
 +    varargout = gf_spmat_get(gf_obj,other_param(:));
 +  case 19 then
++=======
+     // gfMultiContactFrame
+     varargout = gf_multi_contact_frame_get(gf_obj,other_param(:));
+   case 17 then
+     // gfPrecond
+     varargout = gf_precond_get(gf_obj,other_param(:));
+   case 18 then
+     // gfSlice
+     varargout = gf_slice_get(gf_obj,other_param(:));
+   case 19 then
+     // gfSpmat
+     varargout = gf_spmat_get(gf_obj,other_param(:));
+   case 20 then
++>>>>>>> upstream
      // gfPoly
      // No gf_poly_get function
    else
diff --cc interface/src/scilab/macros/overload/%objid_set.sci
index 7cbf9f2,4a43f7f..874083a
--- a/interface/src/scilab/macros/overload/%objid_set.sci
+++ b/interface/src/scilab/macros/overload/%objid_set.sci
@@@ -55,15 -55,18 +55,30 @@@ function %objid_set(varargin
      // gfModel
      gf_model_set(gf_obj,other_param(:));
    case 16 then
++<<<<<<< HEAD
 +    // gfPrecond
 +    // No gf_precond_set function
 +  case 17 then
 +    // gfSlice
 +    gf_slice_set(gf_obj,other_param(:));
 +  case 18 then
 +    // gfSpmat
 +    gf_spmat_set(gf_obj,other_param(:));
 +  case 19 then
++=======
+     // gfMultiContactFrame
+     gf_multi_contact_frame_set(gf_obj,other_param(:));
+   case 17 then
+     // gfPrecond
+     // No gf_precond_set function
+   case 18 then
+     // gfSlice
+     gf_slice_set(gf_obj,other_param(:));
+   case 19 then
+     // gfSpmat
+     gf_spmat_set(gf_obj,other_param(:));
+   case 20 then
++>>>>>>> upstream
      // gfPoly
      // No gf_poly_set function
    else
diff --cc interface/src/scilab/macros/overload/gf_typeof.sci
index 8826df6,9e1572f..878930b
--- a/interface/src/scilab/macros/overload/gf_typeof.sci
+++ b/interface/src/scilab/macros/overload/gf_typeof.sci
@@@ -42,12 -42,14 +42,23 @@@ function res = gf_typeof(gf_var
    case 15 then
      res = 'gfModel';
    case 16 then
++<<<<<<< HEAD
 +    res = 'gfPrecond';
 +  case 17 then
 +    res = 'gfSlice';
 +  case 18 then
 +    res = 'gfSpmat';
 +  case 19 then
++=======
+     res = 'gfMultiContactFrame';
+   case 17 then
+     res = 'gfPrecond';
+   case 18 then
+     res = 'gfSlice';
+   case 19 then
+     res = 'gfSpmat';
+   case 20 then
++>>>>>>> upstream
      res = 'gfPoly';
    else
      error('wrong object ID');
diff --cc interface/src/scilab/sci_gateway/c/builder_gateway_c.sce.in
index eb8a95d,91ae674..96ef032
--- a/interface/src/scilab/sci_gateway/c/builder_gateway_c.sce.in
+++ b/interface/src/scilab/sci_gateway/c/builder_gateway_c.sce.in
@@@ -9,60 -9,63 +9,120 @@@ getfem_path = '@GETFEM_INTERFACE_PATH@'
  
  // Functions extracted from getfem_interface.cc
  
++<<<<<<< HEAD
 +Table = ['gf_workspace',           'sci_gf_scilab'; ...
 +         'gf_delete',              'sci_gf_scilab'; ...
 +         'gf_undelete',            'sci_gf_scilab'; ...
 +         'gf_eltm',                'sci_gf_scilab'; ...
 +         'gf_geotrans',            'sci_gf_scilab'; ...
 +         'gf_geotrans_get',        'sci_gf_scilab'; ...
 +         'gf_integ',               'sci_gf_scilab'; ...
 +         'gf_integ_get',           'sci_gf_scilab'; ...
 +         'gf_global_function',     'sci_gf_scilab'; ...
 +         'gf_global_function_get', 'sci_gf_scilab'; ...
 +         'gf_fem',                 'sci_gf_scilab'; ...
 +         'gf_fem_get',             'sci_gf_scilab'; ...
 +         'gf_cvstruct_get',        'sci_gf_scilab'; ...
 +         'gf_mesher_object',       'sci_gf_scilab'; ...
 +         'gf_mesher_object_get',   'sci_gf_scilab'; ...
 +         'gf_mesh',                'sci_gf_scilab'; ...
 +         'gf_mesh_get',            'sci_gf_scilab'; ...
 +         'gf_mesh_set',            'sci_gf_scilab'; ...
 +         'gf_mesh_fem',            'sci_gf_scilab'; ...
 +         'gf_mesh_fem_get',        'sci_gf_scilab'; ...
 +         'gf_mesh_fem_set',        'sci_gf_scilab'; ...
 +         'gf_mesh_im',             'sci_gf_scilab'; ...
 +         'gf_mesh_im_get',         'sci_gf_scilab'; ...
 +         'gf_mesh_im_set',         'sci_gf_scilab'; ...
 +         'gf_mdbrick',             'sci_gf_scilab'; ...
 +         'gf_mdbrick_get',         'sci_gf_scilab'; ...
 +         'gf_mdbrick_set',         'sci_gf_scilab'; ...
 +         'gf_mdstate',             'sci_gf_scilab'; ...
 +         'gf_mdstate_get',         'sci_gf_scilab'; ...
 +         'gf_mdstate_set',         'sci_gf_scilab'; ...
 +         'gf_model',               'sci_gf_scilab'; ...
 +         'gf_model_get',           'sci_gf_scilab'; ...
 +         'gf_model_set',           'sci_gf_scilab'; ...
 +         'gf_slice',               'sci_gf_scilab'; ...
 +         'gf_slice_get',           'sci_gf_scilab'; ...
 +         'gf_slice_set',           'sci_gf_scilab'; ...
 +         'gf_levelset',            'sci_gf_scilab'; ...
 +         'gf_levelset_get',        'sci_gf_scilab'; ...
 +         'gf_levelset_set',        'sci_gf_scilab'; ...
 +         'gf_mesh_levelset',       'sci_gf_scilab'; ...
 +         'gf_mesh_levelset_get',   'sci_gf_scilab'; ...
 +         'gf_mesh_levelset_set',   'sci_gf_scilab'; ...
 +         'gf_asm',                 'sci_gf_scilab'; ...
 +         'gf_compute',             'sci_gf_scilab'; ...
 +         'gf_precond',             'sci_gf_scilab'; ...
 +         'gf_precond_get',         'sci_gf_scilab'; ...
 +         'gf_spmat',               'sci_gf_scilab'; ...
 +         'gf_spmat_get',           'sci_gf_scilab'; ...
 +         'gf_spmat_set',           'sci_gf_scilab'; ...
 +         'gf_linsolve',            'sci_gf_scilab'; ...
 +         'gf_util',                'sci_gf_scilab'; ...
 +         'gf_exit',                'sci_gf_scilab'; ...
 +	 'gf_cont_struct_get',     'sci_gf_scilab'; ...
 +	 'gf_cont_struct',         'sci_gf_scilab'];
++=======
+ Table = ['gf_workspace',               'sci_gf_scilab'; ...
+          'gf_delete',                  'sci_gf_scilab'; ...
+          'gf_undelete',                'sci_gf_scilab'; ...
+          'gf_eltm',                    'sci_gf_scilab'; ...
+          'gf_geotrans',                'sci_gf_scilab'; ...
+          'gf_geotrans_get',            'sci_gf_scilab'; ...
+          'gf_integ',                   'sci_gf_scilab'; ...
+          'gf_integ_get',               'sci_gf_scilab'; ...
+          'gf_global_function',         'sci_gf_scilab'; ...
+          'gf_global_function_get',     'sci_gf_scilab'; ...
+          'gf_fem',                     'sci_gf_scilab'; ...
+          'gf_fem_get',                 'sci_gf_scilab'; ...
+          'gf_cvstruct_get',            'sci_gf_scilab'; ...
+          'gf_mesher_object',           'sci_gf_scilab'; ...
+          'gf_mesher_object_get',       'sci_gf_scilab'; ...
+          'gf_mesh',                    'sci_gf_scilab'; ...
+          'gf_mesh_get',                'sci_gf_scilab'; ...
+          'gf_mesh_set',                'sci_gf_scilab'; ...
+          'gf_mesh_fem',                'sci_gf_scilab'; ...
+          'gf_mesh_fem_get',            'sci_gf_scilab'; ...
+          'gf_mesh_fem_set',            'sci_gf_scilab'; ...
+          'gf_mesh_im',                 'sci_gf_scilab'; ...
+          'gf_mesh_im_get',             'sci_gf_scilab'; ...
+          'gf_mesh_im_set',             'sci_gf_scilab'; ...
+          'gf_mdbrick',                 'sci_gf_scilab'; ...
+          'gf_mdbrick_get',             'sci_gf_scilab'; ...
+          'gf_mdbrick_set',             'sci_gf_scilab'; ...
+          'gf_mdstate',                 'sci_gf_scilab'; ...
+          'gf_mdstate_get',             'sci_gf_scilab'; ...
+          'gf_mdstate_set',             'sci_gf_scilab'; ...
+          'gf_model',                   'sci_gf_scilab'; ...
+          'gf_model_get',               'sci_gf_scilab'; ...
+          'gf_model_set',               'sci_gf_scilab'; ...
+          'gf_slice',                   'sci_gf_scilab'; ...
+          'gf_slice_get',               'sci_gf_scilab'; ...
+          'gf_slice_set',               'sci_gf_scilab'; ...
+          'gf_levelset',                'sci_gf_scilab'; ...
+          'gf_levelset_get',            'sci_gf_scilab'; ...
+          'gf_levelset_set',            'sci_gf_scilab'; ...
+          'gf_mesh_levelset',           'sci_gf_scilab'; ...
+          'gf_mesh_levelset_get',       'sci_gf_scilab'; ...
+          'gf_mesh_levelset_set',       'sci_gf_scilab'; ...
+          'gf_asm',                     'sci_gf_scilab'; ...
+          'gf_compute',                 'sci_gf_scilab'; ...
+          'gf_precond',                 'sci_gf_scilab'; ...
+          'gf_precond_get',             'sci_gf_scilab'; ...
+          'gf_spmat',                   'sci_gf_scilab'; ...
+          'gf_spmat_get',               'sci_gf_scilab'; ...
+          'gf_spmat_set',               'sci_gf_scilab'; ...
+          'gf_linsolve',                'sci_gf_scilab'; ...
+          'gf_util',                    'sci_gf_scilab'; ...
+          'gf_exit',                    'sci_gf_scilab'; ...
+ 	 'gf_cont_struct_get',         'sci_gf_scilab'; ...
+ 	 'gf_cont_struct',             'sci_gf_scilab'; ...
+ 	 'gf_multi_contact_frame_get', 'sci_gf_scilab'; ...
+ 	 'gf_multi_contact_frame_set', 'sci_gf_scilab'; ...
+ 	 'gf_multi_contact_frame',     'sci_gf_scilab'];
++>>>>>>> upstream
  
  // Special functions added for matlab compatibility
  
@@@ -86,6 -89,20 +146,23 @@@ Libraries = ['../../src/c/libsp_get']
  if getos()=='Windows' then
    getfem_path = pwd() + '\..\..\..\';
    
++<<<<<<< HEAD
++=======
+   // rebuild parameters.lib
+   exec(path_builder + 'rebuild_lib_windows.sci');
+   // We need to use Visual studio 10.0
+   if win64() then
+     machine = 'X64';
+   else
+     machine = 'X86';
+   end
+   status = rebuild_lib_windows(filtersd_path,'sparse_f',machine,'10.0');
+   if ~status then
+     printf('Error: problem while rebuilding parameters.lib\n');
+     abort();
+   end
+ 
++>>>>>>> upstream
    cflags = ' /I' + sci_getfem_path + ' /I' + sci_getfem_path + '/../../src/c';
    cflags = cflags + ' /I' + getfem_path + '/interface/src/' + ' /I' + getfem_path + '/src/getfem';
    cflags = cflags + ' /I' + SCI + '/../../include/scilab'; // For the binary distribution
@@@ -100,21 -117,8 +177,26 @@@
    if (isfile(getfem_path + 'msvc2010\muparser_v134\lib\muparser.lib')) then
      ldflags = ldflags + getfem_path + 'msvc2010\muparser_v134\lib\muparser.lib ';
    end  
++<<<<<<< HEAD
 +
 +  // Under windows, scilab ships only sparse_f.dll
 +  // We need first to recreate the lib part 
 +
 +  // * Here are the mingw commands necessary to produce this lib library:
 +  //   echo EXPORT > sparse_f.def
 +  //   nm sparse_f.dll | grep 'T_' | sed 's/.* T _//' > sparse_f.def
 +  //   dll_tool --def sparse_f.def --dllname sparse_f.dll --outputfile sparse_f.lib
 +  // * Here are the visual commands necessary to produce this lib library:
 +  //   dumpbin /exports sparse_f.dll > sparse_f.def
 +  //   Edit sparse_f.def, add 'EXPORTS' on the first line and remove all the
 +  //   cryptic symbols except the symbol name.
 +  //   Now produce the lib file: lib /def:sparse_f.def /OUT:sparse_f.lib
 +    
 +  ldflags = ldflags + ' ' + SCI + '/bin/sparse_f.lib';
++=======
+     
+   ldflags = ldflags + ' sparse_f.lib ';
++>>>>>>> upstream
  
    // ldflags = ldflags + ' /NODEFAULTLIB:LIBCMT';
  else
diff --cc interface/tests/matlab/Makefile.am
index 390fadd,ec66a10..ab9c9a8
--- a/interface/tests/matlab/Makefile.am
+++ b/interface/tests/matlab/Makefile.am
@@@ -49,6 -49,7 +49,10 @@@ EXTRA_DIST= 
  	demo_tripod_slice_anim.m \
  	demo_fictitious_domains.m \
  	demo_fictitious_domains_laplacian.m \
++<<<<<<< HEAD
++=======
+ 	demo_contact_fictitious_domain_nitsche.m \
++>>>>>>> upstream
  	demo_static_contact.m \
  	demo_large_sliding_contact.m \
  	demo_wave2D.m \
diff --cc interface/tests/matlab/demo_continuation.m
index 7298c50,dcab4bd..96e1419
--- a/interface/tests/matlab/demo_continuation.m
+++ b/interface/tests/matlab/demo_continuation.m
@@@ -15,34 -15,42 +15,69 @@@
  % along  with  this program;  if not, write to the Free Software Foundation,
  % Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
  %
++<<<<<<< HEAD
 +% Simple exemple othe f bifurcation problem: -Delta(u) + u = lambda exp(u)
++=======
+ % Simple example of the bifurcation problem: -Delta(u) + u = lambda * exp(u)
++>>>>>>> upstream
  %
  % This program is used to check that matlab-getfem is working. This is also
  % a good example of use of GetFEM++.
  %
  
  gf_workspace('clear all');
++<<<<<<< HEAD
 +
 +lambda = 0;
 +direction = 1;
 +nbstep = 80;
 +
 +maxit = 5;
 +thrit = 4;
 +minang = 0.993;
 +maxres_solve = 1.e-7;
 +noisy = 'very_noisy'
 +
 +h_init = 1e-3;
 +h_max = 2e-1;
 +h_min = 1e-5;
 +
 +with_dirichlet = true;
++=======
+ gf_util('trace level', 1);
+ gf_util('warning level', 3);
+ 
+ % continuation data
+ datapath = 'data/';
+ % If the file name bp_char is non-empty, the continuation will be started
+ % from the bifurcation point and the tangent with the index ind_tangent
+ % saved there, direction of that tangent will be determined by direction.
+ % Otherwise, the continuation will be initialised according to direction and
+ % lambda0.
+ bp_char = '';
+ %bp_char = 'continuation_step_62_bp.mat';
+ ind_tangent = 2;
+ direction = 1;
+ lambda0 = 0;
+ nbstep = 80;
+ 
+ h_init = 2e-2;
+ h_max = 2e-1;
+ h_min = 2e-5;
+ mincos = 0.997;
+ noisy = 'noisy';
+ 
+ with_dirichlet = false;
++>>>>>>> upstream
  
  % create a simple cartesian mesh
  m = gf_mesh('cartesian', [0:.1:1]);
  
++<<<<<<< HEAD
 +% create a mesh_fem of for a field of dimension 1 (i.e. a scalar field)
++=======
+ % create a mesh_fem for a field of dimension 1 (i.e. a scalar field)
++>>>>>>> upstream
  mf = gf_mesh_fem(m,1);
  % assign the P1 fem to all convexes of the mesh_fem,
  gf_mesh_fem_set(mf, 'classical fem', 1);
@@@ -59,50 -67,71 +94,116 @@@ gf_mesh_set(m, 'boundary', 1, border)
  md = gf_model('real');
  gf_model_set(md, 'add fem variable', 'u', mf);
  gf_model_set(md, 'add Laplacian brick', mim, 'u');
++<<<<<<< HEAD
 +gf_model_set(md, 'add initialized data', 'lambda', [lambda]);
 +gf_model_set(md, 'add basic nonlinear brick', mim, 'u', 'u-lambda*exp(u)', '1-lambda*exp(u)', 'lambda');
 +if (with_dirichlet)
 +  gf_model_set(md, 'add Dirichlet condition with multipliers', mim, 'u', mf, 1);
++=======
+ gf_model_set(md, 'add data', 'lambda', 1);
+ gf_model_set(md, 'add basic nonlinear brick', mim, 'u', ...
+              'u-lambda*exp(u)', '1-lambda*exp(u)', 'lambda');
+ if (with_dirichlet)
+   gf_model_set(md, 'add Dirichlet condition with multipliers', ...
+                mim, 'u', mf, 1);
++>>>>>>> upstream
  end;
  
  % initialise the continuation
  scfac = 1 / gf_mesh_fem_get(mf, 'nbdof');
++<<<<<<< HEAD
 +S = gf_cont_struct(md, 'lambda', scfac, 'max_iter', maxit, 'thr_iter', thrit, 'min_ang', minang, 'h_init', h_init, 'h_max', h_max, 'h_min', h_min, noisy);
 +
 +% compute an initial point
 +if (noisy) disp('computing initial point\n'); end
 +gf_model_get(md, 'solve', noisy, 'max iter', 100, 'max_res', maxres_solve);
 +[T_U, T_lambda, h] = gf_cont_struct_get(S, 'init Moore-Penrose continuation', direction);
 +
 +U = gf_model_get(md, 'variable', 'u');
 +disp('U = '); disp(U); disp(sprintf('lambda = %e\n', lambda));
 +disp(sprintf('lambda - U(1) * exp(-U(1)) = %e\n', lambda - U(1) * exp(-U(1))));
 +
 +U_hist = zeros(1, nbstep + 1); lambda_hist = zeros(1, nbstep + 1);
 +U_hist(1) = max(U); lambda_hist(1) = lambda;
++=======
+ S = gf_cont_struct(md, 'lambda', scfac, 'bifurcations', 'h_init', h_init, ...
+                    'h_max', h_max, 'h_min', h_min, 'min_cos', mincos, noisy);
+ 
+ if (bp_char)
+   load([datapath bp_char]);
+   U = U_bp; lambda = lambda_bp;
+   T_U = direction * T_U_bp(:, ind_tangent);
+   T_lambda = direction * T_lambda_bp(ind_tangent);
+   h = gf_cont_struct_get(S, 'init step size');
+ else
+   lambda = lambda0;
+   gf_model_set(md, 'variable', 'lambda', [lambda]);
+   
+   if (noisy) disp('starting computing an initial point'); end
+   gf_model_get(md, 'solve', noisy, 'max iter', 100);
+   U = gf_model_get(md, 'variable', 'u');
+   [T_U, T_lambda, h] = ...
+     gf_cont_struct_get(S, 'init Moore-Penrose continuation', ...
+                        U, lambda, direction);
+ end
+ 
+ U_hist = zeros(1, nbstep + 1); lambda_hist = zeros(1, nbstep + 1);
+ U_hist(1) = U(1); lambda_hist(1) = lambda;
++>>>>>>> upstream
  
  figure(1);
  subplot(2,1,1);
  plot(lambda_hist(1), U_hist(1), 'k.');
++<<<<<<< HEAD
 +xlabel('lambda'); ylabel('max(u)');
 +if (with_dirichlet) axis([0 4 0 10]); else axis([0 0.4 0 11]); end
 +subplot(2,1,2)
 +gf_plot_1D(mf, U, 'style', 'k.-');
 +if (with_dirichlet) axis([0 1 0 10]); else axis([0 1 0 11]); end  
 +xlabel('x'); ylabel('u');
 +pause(1);
 +
 +% continue from the initial point
 +for step = 1:nbstep
 +  disp(sprintf('\nbeginning of step %d\n', step));
 +  [T_U, T_lambda, h] = gf_cont_struct_get(S, 'Moore-Penrose continuation', T_U, T_lambda, h);
 +  U = gf_model_get(md, 'variable', 'u');
 +  lambda = gf_model_get(md, 'variable', 'lambda');
 +  % disp('U = '); disp(U);
 +  disp(sprintf('lambda = %e\n', lambda));
 +  % disp(sprintf('lambda - U(1) * exp(-U(1)) = %e\n', lambda - U(1) * exp(-U(1))));
 +   
 +  U_hist(step+1) = max(U); lambda_hist(step+1) = lambda;
++=======
+ xlabel('lambda'); ylabel('U(1)');
+ if (with_dirichlet) axis([0 4 0 15]); else axis([0 0.4 0 15]); end
+ subplot(2,1,2)
+ gf_plot_1D(mf, U, 'style', 'k.-');
+ if (with_dirichlet) axis([0 1 0 15]); else axis([0 1 0 15]); end  
+ xlabel('x'); ylabel('u');
+ pause(1);
+ 
+ sing_out = [];
+ % continue from the initial point
+ for step = 1:nbstep
+   disp(sprintf('\nbeginning of step %d', step));
+   [U, lambda, T_U, T_lambda, h, sing_label] = ...
+     gf_cont_struct_get(S, 'Moore-Penrose continuation', ...
+                        U, lambda, T_U, T_lambda, h);
+                        
+   if (h ==0) return
+   elseif (strcmp(sing_label, 'smooth bifurcation point'))
+      [U_bp, lambda_bp, T_U_bp, T_lambda_bp]...
+        = gf_cont_struct_get(S, 'sing_data');
+      save([datapath 'continuation_step_' sprintf('%d', step) '_bp.mat'], ...
+           'U_bp', 'lambda_bp', 'T_U_bp', 'T_lambda_bp');
+      s = ['step ' sprintf('%d', step) ': ' sprintf('%d', size(T_U_bp, 2)) ...
+           ' branch(es) located'];
+      sing_out = [sing_out; s];
+   end
+   
+   U_hist(step+1) = U(1); lambda_hist(step+1) = lambda;
++>>>>>>> upstream
      
    subplot(2,1,1);
    plot(lambda_hist(1:step+1), U_hist(1:step+1), 'k-');
@@@ -110,16 -139,25 +211,38 @@@
    plot(lambda_hist(1:step), U_hist(1:step), 'ko');
    plot(lambda_hist(step+1), U_hist(step+1), 'k.');
    hold off;
++<<<<<<< HEAD
 +  if (with_dirichlet) axis([0 4 0 10]); else axis([0 0.4 0 11]); end
 +  xlabel('lambda'); ylabel('max(u)');
 +  subplot(2,1,2)
 +  gf_plot_1D(mf, U, 'style', 'k.-');
 +  if (with_dirichlet) axis([0 1 0 10]); else axis([0 1 0 11]); end
 +  xlabel('x'); ylabel('u');
 +  pause(0.25);
 +  disp(sprintf('end of step n° %d', step)); disp(sprintf(' / %d\n', nbstep));
 +end
 +
++=======
+   if (with_dirichlet) axis([0 4 0 15]); else axis([0 0.4 0 15]); end
+   xlabel('lambda'); ylabel('U(1)');
+   subplot(2,1,2)
+   gf_plot_1D(mf, U, 'style', 'k.-');
+   if (with_dirichlet) axis([0 1 0 15]); else axis([0 1 0 15]); end
+   xlabel('x'); ylabel('u');
+   pause(0.25);
+   disp(sprintf('end of step n° %d / %d', step, nbstep));
+ end
+ 
+ nsing = size(sing_out, 1);
+ if (nsing)
+   disp(sprintf('\n----------------------------------------------------------'))
+   disp('   detected bifurcation points on the continuation curve')
+   disp('----------------------------------------------------------')
+   for i = 1:nsing
+     disp(sing_out(i,:))
+   end
+ end
++>>>>>>> upstream
  
  
  % gf_plot(mf,U,'mesh','on','contour',.01:.01:.1); 
diff --cc interface/tests/matlab/demo_fictitious_domains_laplacian.m
index e32bedc,7eb790c..8e97f30
--- a/interface/tests/matlab/demo_fictitious_domains_laplacian.m
+++ b/interface/tests/matlab/demo_fictitious_domains_laplacian.m
@@@ -25,7 -25,7 +25,11 @@@ gf_workspace('clear all')
  
    
  
++<<<<<<< HEAD
 +NX=30
++=======
+ NX= 10
++>>>>>>> upstream
  N = 3
  ls_degree = 1
  R = 0.4;
diff --cc interface/tests/matlab/demo_laplacian.m
index 28a5deb,7392acb..9f13c2a
--- a/interface/tests/matlab/demo_laplacian.m
+++ b/interface/tests/matlab/demo_laplacian.m
@@@ -15,6 -15,12 +15,15 @@@
  % along  with  this program;  if not, write to the Free Software Foundation,
  % Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
  
++<<<<<<< HEAD
++=======
+ % Options for prescribing the Dirichlet condition
+ dirichlet_version = 1; % 0 = simplification, 1 = with multipliers, 2 = penalization,  3 = Nitsche's method
+ theta = 1;       % Nitsche's method parameter theta
+ gamma0 = 0.001;  % Nitsche's method parameter gamma0 (gamma = gamma0*h)
+ r = 1e8;         % Penalization parameter
+ draw = true;
++>>>>>>> upstream
  
  % trace on;
  gf_workspace('clear all');
diff --cc interface/tests/matlab/demo_large_sliding_contact.m
index 3c6b084,991edfc..0ec1667
--- a/interface/tests/matlab/demo_large_sliding_contact.m
+++ b/interface/tests/matlab/demo_large_sliding_contact.m
@@@ -1,4 -1,4 +1,8 @@@
++<<<<<<< HEAD
 +% Copyright (C) 2012-2012 Yves Renard.
++=======
+ % Copyright (C) 2012-2013 Yves Renard.
++>>>>>>> upstream
  %
  % This file is a part of GETFEM++
  %
@@@ -15,124 -15,328 +19,448 @@@
  % along  with  this program;  if not, write to the Free Software Foundation,
  % Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
  
++<<<<<<< HEAD
 +gf_workspace('clear all');
 +clear all;
 +
 +lambda = 1.; mu = 1.;   % Elasticity parameters
 +r = 1.0;                % Augmentation parameter
 +f_coeff = 1.;           % Friction coefficient
 +vf = 0.01;                % Vertical force
 +penalty_parameter = 0.1;
 +
 +
 +mesh1 = gf_mesh('load', '../../../tests/meshes/disc_with_a_hole.mesh');
 +mesh2 = gf_mesh('import', 'structured', 'GT="GT_PK(2,1)";ORG=[-0.5,0];SIZES=[1,0.1];NSUBDIV=[20,2]');
++=======
+ 
+ clear all;
+ gf_workspace('clear all');
+ 
+ test_case = 1; % 0 = 2D punch on a rigid obstacle
+                % 1 = 2D punch on a deformable obstacle (one slave, one master)
+                % 2 = 2D with two different meshes
+                % 3 = 2D with multi-body and only one mesh
+                % 4 = 3D case (sphere / parallelepiped) (two meshes)
+ 
+ clambda1 = 1.; cmu1 = 1.;   % Elasticity parameters
+ clambda2 = 1.; cmu2 = 1.;   % Elasticity parameters
+ r = 0.1;                    % Augmentation parameter
+ alpha = 0;                  % Alpha coefficient for "sliding velocity"
+ f_coeff = 0;                % Friction coefficient
+ 
+ test_tangent_matrix = true;
+ nonlinear_elasticity = false;
+ max_iter = 50;
+ draw_mesh = false;
+ 
+ switch(test_case)
+   case {0,1}
+     vf = 0.0;
+     vf_mult = 1.0;
+     penalty_parameter = 0;
+     dirichlet_translation = -0.5;
+     max_res = 1E-8;
+     release_dist = 1.5;
+     self_contact = false;
+   case 3
+     vf = 0.01;              % Vertical force
+     vf_mult = 1.05;
+     penalty_parameter = 0.1;
+     release_dist = 0.05;
+     max_res = 1E-8;
+     self_contact = true;
+   case {2,4}
+     vf = 0.01;              % Vertical force
+     vf_mult = 1.5;
+     penalty_parameter = 0.01;
+     max_res = 1E-8;
+     if (test_case == 2)
+       release_dist = 0.1;
+     else
+       release_dist = 5;
+     end
+     self_contact = true;
+ end;    
+ 
+ switch (test_case) 
+   case 0
+     % mesh1 = gf_mesh('load', '../../../tests/meshes/punch2D_1.mesh');
+     mesh1 = gf_mesh('load', '../../../tests/meshes/punch2D_2.mesh');
+   case 1
+     % mesh1 = gf_mesh('load', '../../../tests/meshes/punch2D_1.mesh');
+     mesh1 = gf_mesh('load', '../../../tests/meshes/punch2D_2.mesh');
+     mesh2 = gf_mesh('import', 'structured', 'GT="GT_PK(2,1)";ORG=[-14,-5];SIZES=[28,5];NSUBDIV=[28,5]');
+   case 2
+     mesh1 = gf_mesh('load', '../../../tests/meshes/disc_with_a_hole.mesh');
+     % mesh1 = gf_mesh('import', 'structured', 'GT="GT_PK(2,1)";ORG=[-0.5,0.1];SIZES=[1,0.1];NSUBDIV=[20,2]');
+     mesh2 = gf_mesh('import', 'structured', 'GT="GT_PK(2,1)";ORG=[-0.5,0];SIZES=[1,0.1];NSUBDIV=[20,2]');
+   case 3
+     mesh1 = gf_mesh('load', '../../../tests/meshes/multi_body.mesh');
+   case 4
+     mesh1 = gf_mesh('load', '../../../tests/meshes/sphere_with_quadratic_tetra_400_elts.mesh');
+     mesh2 = gf_mesh('import', 'structured', 'GT="GT_PK(3,1)";ORG=[-15,-15,-4];SIZES=[30,30,4];NSUBDIV=[10,10,2]');
+ end
++>>>>>>> upstream
  
  N = gf_mesh_get(mesh1, 'dim');
  
  mfu1 = gf_mesh_fem(mesh1, N); gf_mesh_fem_set(mfu1, 'classical fem', 2);
  pre_mflambda1 = gf_mesh_fem(mesh1, N); gf_mesh_fem_set(pre_mflambda1, 'classical fem', 1);
  mfvm1 = gf_mesh_fem(mesh1); gf_mesh_fem_set(mfvm1, 'classical discontinuous fem', 1);
++<<<<<<< HEAD
 +fb1 = gf_mesh_get(mesh1, 'outer faces');
 +CONTACT_BOUNDARY1 = 1;
 +gf_mesh_set(mesh1,'boundary', CONTACT_BOUNDARY1, fb1);
 +dol1 = gf_mesh_fem_get(pre_mflambda1, 'basic dof on region', CONTACT_BOUNDARY1);
 +mflambda1 = gf_mesh_fem('partial',  pre_mflambda1, dol1);
 +mim1 = gf_mesh_im(mesh1, 4);
 +
 +
 +mfu2 = gf_mesh_fem(mesh2, N); gf_mesh_fem_set(mfu2, 'classical fem', 1);
 +pre_mflambda2 = gf_mesh_fem(mesh2, N); gf_mesh_fem_set(pre_mflambda2, 'classical fem', 1);
 +mfvm2 = gf_mesh_fem(mesh2); gf_mesh_fem_set(mfvm2, 'classical discontinuous fem', 1);
 +fb2 = gf_mesh_get(mesh2, 'outer faces');
 +CONTACT_BOUNDARY2 = 2;
 +gf_mesh_set(mesh2,'boundary', CONTACT_BOUNDARY2, fb2);
 +dol2 = gf_mesh_fem_get(pre_mflambda2, 'basic dof on region', CONTACT_BOUNDARY2);
 +mflambda2 = gf_mesh_fem('partial',  pre_mflambda2, dol2);
 +mim2 = gf_mesh_im(mesh2, 8);
 +
 +two_bodies = 1;
 +
 +md=gf_model('real');
 +gf_model_set(md, 'add initialized data', 'lambda', lambda);
 +gf_model_set(md, 'add initialized data', 'mu', mu);
 +
 +if (two_bodies) 
 +  gf_model_set(md, 'add fem variable', 'u1', mfu1);
 +  gf_model_set(md, 'add fem variable', 'lambda1', mflambda1);
 +  gf_model_set(md, 'add isotropic linearized elasticity brick', mim1, 'u1', 'lambda', 'mu');
 +%   gf_model_set(md, 'add initialized data', 'cpoints1', [0 0.5 0 1.5 0 0.5 0 1.5]);
 +%   gf_model_set(md, 'add initialized data', 'cunitv1', [1 0 1 0 0 1 0 1]);
 +%   gf_model_set(md, 'add initialized data', 'cdata', [0 0 -0.01 -0.01]);
 +%   gf_model_set(md, 'add pointwise constraints with multipliers', 'u1', 'cpoints1', 'cunitv1', 'cdata');
++=======
+ CONTACT_BOUNDARY1 = 1;
+ DIRICHLET_BOUNDARY1 = 3;
+ if (test_case >= 2)
+   fb1 = gf_mesh_get(mesh1, 'outer faces');
+   gf_mesh_set(mesh1,'region', CONTACT_BOUNDARY1, fb1);
+ else
+   border = gf_mesh_get(mesh1,'outer faces');
+   normals = gf_mesh_get(mesh1, 'normal of faces', border);
+   contact_boundary=border(:, find(normals(N, :) < -0.01));
+   gf_mesh_set(mesh1, 'region', CONTACT_BOUNDARY1, contact_boundary);
+   P=gf_mesh_get(mesh1,'pts'); % get list of mesh points coordinates
+   pidtop=find(P(N,:) > 39.999); % find those on top of the object
+   ftop=gf_mesh_get(mesh1,'faces from pid',pidtop); 
+   gf_mesh_set(mesh1, 'region', DIRICHLET_BOUNDARY1, ftop);
+ end
+ 
+ 
+ 
+ 
+ % dol1 = gf_mesh_fem_get(pre_mflambda1, 'basic dof on region', CONTACT_BOUNDARY1);
+ % mflambda1 = gf_mesh_fem('partial',  pre_mflambda1, dol1);
+ mim1 = gf_mesh_im(mesh1, 4);
+ mim1_contact = gf_mesh_im(mesh1, 4);
+ 
+ if (test_case ~= 3 && test_case ~= 0) 
+   mfu2 = gf_mesh_fem(mesh2, N); gf_mesh_fem_set(mfu2, 'classical fem', 2);
+   pre_mflambda2 = gf_mesh_fem(mesh2, N); gf_mesh_fem_set(pre_mflambda2, 'classical fem', 1);
+   mfvm2 = gf_mesh_fem(mesh2); gf_mesh_fem_set(mfvm2, 'classical discontinuous fem', 1);
+   
+   CONTACT_BOUNDARY2 = 2;
+   if (test_case ~= 1)
+     fb2 = gf_mesh_get(mesh2, 'outer faces');
+     gf_mesh_set(mesh2,'region', CONTACT_BOUNDARY2, fb2);
+   else
+     border = gf_mesh_get(mesh2,'outer faces');
+     normals = gf_mesh_get(mesh2, 'normal of faces', border);
+     contact_boundary=border(:, find(normals(N, :) > 0.01));
+     gf_mesh_set(mesh2, 'region', CONTACT_BOUNDARY2, contact_boundary);
+     dirichlet_boundary=border(:, find(normals(N, :) < -0.01));
+     DIRICHLET_BOUNDARY2 = 5;
+     gf_mesh_set(mesh2, 'region', DIRICHLET_BOUNDARY2, dirichlet_boundary);
+   end
+   mim2 = gf_mesh_im(mesh2, 4);
+   mim2_contact = gf_mesh_im(mesh2, 4);
+ end
+ 
+ if (draw_mesh)
+   gf_plot_mesh(mesh1, 'regions', CONTACT_BOUNDARY1);
+   if (test_case ~= 3 && test_case ~= 0) 
+     hold on
+     gf_plot_mesh(mesh2, 'regions', CONTACT_BOUNDARY2);
+     hold off
+   end
+   pause;
+ end
+ 
+ 
+ md=gf_model('real');
+ 
+ F = zeros(1, N); F(N) = -vf;
+ 
+ gf_model_set(md, 'add fem variable', 'u1', mfu1);
+ gf_model_set(md, 'add filtered fem variable', 'lambda1', pre_mflambda1, CONTACT_BOUNDARY1);
+ 
+ if (nonlinear_elasticity)
+   lawname = 'Ciarlet Geymonat';
+   params1 = [clambda1;cmu1;cmu1/2-clambda1/8];
+   gf_model_set(md,'add initialized data','params1', params1);
+   gf_model_set(md, 'add nonlinear elasticity brick', mim1, 'u1', lawname, 'params1');
+ else
+   gf_model_set(md, 'add initialized data', 'clambda1', clambda1);
+   gf_model_set(md, 'add initialized data', 'cmu1', cmu1);
+   gf_model_set(md, 'add isotropic linearized elasticity brick', mim1, 'u1', 'clambda1', 'cmu1');
+ end
+ if (test_case == 2)
+   %   gf_model_set(md, 'add initialized data', 'cpoints1', [0 0.5 0 1.5 0 0.5 0 1.5]);
+   %   gf_model_set(md, 'add initialized data', 'cunitv1', [1 0 1 0 0 1 0 1]);
+   %   gf_model_set(md, 'add initialized data', 'cdata', [0 0 -0.01 -0.01]);
+   %   gf_model_set(md, 'add pointwise constraints with multipliers', 'u1', 'cpoints1', 'cunitv1', 'cdata');
++>>>>>>> upstream
    gf_model_set(md, 'add initialized data', 'cpoints1', [0 0.5 0 1.5]);
    gf_model_set(md, 'add initialized data', 'cunitv1', [1 0 1 0]);
    gf_model_set(md, 'add initialized data', 'cdata', [0 0]);
    gf_model_set(md, 'add pointwise constraints with multipliers', 'u1', 'cpoints1', 'cunitv1', 'cdata');
++<<<<<<< HEAD
 +  gf_model_set(md, 'add initialized data', 'data1', [0 -vf]);
 +  gf_model_set(md, 'add source term brick', mim1, 'u1', 'data1');
 +  gf_model_set(md, 'add initialized data', 'penalty_param1', [penalty_parameter]);          
 +  gf_model_set(md, 'add mass brick', mim1, 'u1', 'penalty_param1');
 +end;
 +
 +gf_model_set(md, 'add fem variable', 'u2', mfu2);
 +gf_model_set(md, 'add fem variable', 'lambda2', mflambda2);
 +gf_model_set(md, 'add isotropic linearized elasticity brick', mim2, 'u2', 'lambda', 'mu');
 +gf_model_set(md, 'add initialized data', 'cpoints2', [0 0]);
 +gf_model_set(md, 'add initialized data', 'cunitv2', [1 0]);
 +gf_model_set(md, 'add pointwise constraints with multipliers', 'u2', 'cpoints2', 'cunitv2');
 +gf_model_set(md, 'add initialized data', 'data2', [0 -vf]);
 +gf_model_set(md, 'add source term brick', mim2, 'u2', 'data2');
 +gf_model_set(md, 'add initialized data', 'penalty_param2', [penalty_parameter]);          
 +gf_model_set(md, 'add mass brick', mim2, 'u2', 'penalty_param2');
 +
 +gf_model_set(md, 'add initialized data', 'r', r);
 +gf_model_set(md, 'add initialized data', 'f', f_coeff);
 +
 +indb = gf_model_set(md, 'add integral large sliding contact brick', mim2, 'u2', 'lambda2', 'r', 'f', CONTACT_BOUNDARY2);
 +
 +if (two_bodies) 
 +  gf_model_set(md, 'add boundary to large sliding contact brick', indb, mim1, 'u1', 'lambda1', CONTACT_BOUNDARY1);
 +end;
 +
 +gf_model_set(md, 'add rigid obstacle to large sliding contact brick', indb, 'y');
 +
 +% gf_model_get(md, 'test tangent matrix', 1E-6, 10, 0.00001);
 +
 +
 +
 +for i=1:100
 +
 +   
 +    
 +gf_model_get(md, 'solve', 'noisy', 'max_iter', 50, 'max_res', 1e-8); % , 'lsearch', 'simplest');
 +
 +U2 = gf_model_get(md, 'variable', 'u2');
 +VM2 = gf_model_get(md, 'compute_isotropic_linearized_Von_Mises_or_Tresca', ...
 +		  'u2', 'lambda', 'mu', mfvm2);
 +
 +gf_plot(mfvm2,VM2,'mesh','off', 'deformation',U2,'deformation_mf',mfu2,'deformation_scale', 1, 'refine', 8); colorbar;
 +
 +if (two_bodies)
 +   hold on
 +   U1 = gf_model_get(md, 'variable', 'u1');
 +   VM1 = gf_model_get(md, 'compute_isotropic_linearized_Von_Mises_or_Tresca', ...
 +		  'u1', 'lambda', 'mu', mfvm1);
 +   gf_plot(mfvm1,VM1,'mesh','off', 'deformation',U1,'deformation_mf',mfu1,'deformation_scale', 1, 'refine', 8); colorbar;
 +   hold off
 +end;
 +
 +axis([-2, 2, -0.2, 3]);
 +pause(1);
 +
 + vf = vf + 0.001;
 + gf_model_set(md, 'variable', 'data1', [0 -vf]);
 + gf_model_set(md, 'variable', 'data2', [0 -vf]);
 +
 +end;
 +
 +
 +
 +
 +
 +
++=======
+ end
+ gf_model_set(md, 'add initialized data', 'penalty_param1', [penalty_parameter]);
+ indmass = gf_model_set(md, 'add mass brick', mim1, 'u1', 'penalty_param1');
+ gf_model_set(md, 'add initialized data', 'data1', F);
+ gf_model_set(md, 'add source term brick', mim1, 'u1', 'data1');
+ 
+ if (test_case ~= 3 && test_case ~= 0)
+   gf_model_set(md, 'add fem variable', 'u2', mfu2);
+   if (self_contact)
+     gf_model_set(md, 'add filtered fem variable', 'lambda2', pre_mflambda2, CONTACT_BOUNDARY2);
+   end
+   
+   if (nonlinear_elasticity)
+     lawname = 'Ciarlet Geymonat';
+     params2 = [clambda2;cmu2;cmu2/2-clambda2/8];
+     gf_model_set(md,'add initialized data','params2', params2);
+     gf_model_set(md, 'add nonlinear elasticity brick', mim2, 'u2', lawname, 'params2');
+   else
+     gf_model_set(md, 'add initialized data', 'clambda2', clambda2);
+     gf_model_set(md, 'add initialized data', 'cmu2', cmu2);
+     gf_model_set(md, 'add isotropic linearized elasticity brick', mim2, 'u2', 'clambda2', 'cmu2');
+   end
+   if (test_case == 2)
+     gf_model_set(md, 'add initialized data', 'cpoints2', [0 0]);
+     gf_model_set(md, 'add initialized data', 'cunitv2', [1 0]);
+     gf_model_set(md, 'add pointwise constraints with multipliers', 'u2', 'cpoints2', 'cunitv2');
+   end
+   gf_model_set(md, 'add initialized data', 'penalty_param2', [penalty_parameter]);          
+   gf_model_set(md, 'add mass brick', mim2, 'u2', 'penalty_param2');
+   gf_model_set(md, 'add initialized data', 'data2', F);
+   gf_model_set(md, 'add source term brick', mim2, 'u2', 'data2');
+   if (test_case == 1)
+     Ddata = zeros(1, N);
+     gf_model_set(md, 'add initialized data', 'Ddata2', Ddata);
+     gf_model_set(md, 'add Dirichlet condition with multipliers', mim2, 'u2', 1, DIRICHLET_BOUNDARY2, 'Ddata2');
+   end
+ end
+ 
+ if (test_case <= 1)
+   Ddata = zeros(1, N); Ddata(N) = dirichlet_translation;
+   gf_model_set(md, 'add initialized data', 'Ddata', Ddata);
+   gf_model_set(md, 'add Dirichlet condition with multipliers', mim1, 'u1', 1, DIRICHLET_BOUNDARY1, 'Ddata');
+ end
+   
+ 
+ 
+ 
+ mcff=gf_multi_contact_frame(md, N, release_dist, false, self_contact, 0.2, true, 0, false);
+ if (self_contact)
+   gf_multi_contact_frame_set(mcff, 'add master boundary', mim1_contact, CONTACT_BOUNDARY1, 'u1', 'lambda1');
+ else
+   gf_multi_contact_frame_set(mcff, 'add slave boundary', mim1_contact, CONTACT_BOUNDARY1, 'u1', 'lambda1'); 
+ end
+ 
+ switch(test_case)
+   case 0
+     gf_multi_contact_frame_set(mcff, 'add obstacle', '80-sqrt(x^2+(y-80)^2)'); 
+   case 1
+     if (self_contact)
+       gf_multi_contact_frame_set(mcff, 'add master boundary', mim2_contact, CONTACT_BOUNDARY2, 'u2', 'lambda2');
+     else
+       gf_multi_contact_frame_set(mcff, 'add master boundary', mim2_contact, CONTACT_BOUNDARY2, 'u2');
+     end
+    case 2
+     gf_multi_contact_frame_set(mcff, 'add master boundary', mim2_contact, CONTACT_BOUNDARY2, 'u2', 'lambda2');
+     gf_multi_contact_frame_set(mcff, 'add obstacle', 'y');
+   case 3
+     gf_multi_contact_frame_set(mcff, 'add obstacle', '2-sqrt(x^2+(y-1)^2)');  
+   case 4
+     gf_multi_contact_frame_set(mcff, 'add master boundary', mim2_contact, CONTACT_BOUNDARY2, 'u2', 'lambda2');
+     gf_multi_contact_frame_set(mcff, 'add obstacle', 'z+5');
+ end
+ 
+ gf_model_set(md, 'add initialized data', 'r', r);
+ gf_model_set(md, 'add initialized data', 'alpha', alpha);
+ gf_model_set(md, 'add initialized data', 'f', f_coeff);
+ gf_model_set(md, 'add integral large sliding contact brick raytrace', mcff, 'r', 'f', 'alpha');
+ 
+ 
+ for nit=1:10000
+   disp(sprintf('Iteration %d', nit));
+ 
+   if (test_tangent_matrix) 
+     errmax = gf_model_get(md, 'test tangent matrix', 1E-8, 20, 0.0001);
+     % errmax = gf_model_get(md, 'test tangent matrix term', 'lambda1', 'u1', 1E-8, 20, 0.0001);
+     disp(sprintf('errmax = %g', errmax));
+     if (errmax > 1E-3) error('bad tangent matrix'); end;
+     pause;
+   end
+     
+   gf_model_get(md, 'solve', 'noisy', 'max_iter', max_iter, 'max_res', max_res); % , 'lsearch', 'simplest');
+ 
+   U1 = gf_model_get(md, 'variable', 'u1');
+   if (nonlinear_elasticity)
+     VM1 = gf_model_get(md, 'compute Von Mises or Tresca', 'u1', lawname, 'params1', mfvm1);
+   else
+     VM1 = gf_model_get(md, 'compute_isotropic_linearized_Von_Mises_or_Tresca', ...
+ 	  	  'u1', 'clambda1', 'cmu1', mfvm1);
+   end
+   gf_plot(mfvm1,VM1,'mesh', 'off', 'deformed_mesh','on', 'deformation',U1,'deformation_mf',mfu1,'deformation_scale', 1, 'refine', 8); colorbar;
+ 
+   hold on % quiver plot of the multiplier
+   lambda1 = gf_model_get(md, 'variable', 'lambda1');
+   mf_lambda1 = gf_model_get(md, 'mesh fem of variable', 'lambda1');
+   sl=gf_slice({'boundary'}, mf_lambda1, CONTACT_BOUNDARY1);
+   bound_lambda1=gf_compute(mf_lambda1, lambda1,'interpolate on', sl);
+   bound_u1=gf_compute(mfu1, U1,'interpolate on', sl);
+   pts = gf_slice_get(sl, 'pts');
+   quiver(bound_u1(1,:)+pts(1,:), bound_u1(2,:)+pts(2,:), bound_lambda1(1,:), bound_lambda1(2,:))
+   hold off
+   
+   % hold on
+   % gf_plot(mf_lambda1, lambda1,'mesh', 'off', 'deformed_mesh','off', 'deformation',U1,'deformation_mf',mfu1,'deformation_scale', 1, 'refine', 8);
+   % hold off
+   
+   if (test_case ~= 3 && test_case ~= 0)
+      hold on
+      U2 = gf_model_get(md, 'variable', 'u2');
+      if (nonlinear_elasticity)
+        VM2 = gf_model_get(md, 'compute Von Mises or Tresca', 'u2', lawname, 'params2', mfvm2);
+      else
+        VM2 = gf_model_get(md, 'compute_isotropic_linearized_Von_Mises_or_Tresca', ...
+ 		    'u2', 'clambda2', 'cmu2', mfvm2);
+      end
+      gf_plot(mfvm2,VM2,'mesh', 'off', 'deformed_mesh','on', 'deformation',U2,'deformation_mf',mfu2,'deformation_scale', 1, 'refine', 8); colorbar;
+      hold off
+   end;
+ 
+   hold on
+   % tic;
+   % gf_multi_contact_frame_get(mcff, 'compute pairs');
+   % toc
+   slpt = gf_multi_contact_frame_get(mcff, 'slave points');
+   mapt = gf_multi_contact_frame_get(mcff, 'master points');
+   if (N == 2)
+     line([slpt(1,:); mapt(1,:)], [slpt(2,:); mapt(2,:)], 'Color', 'blue');
+     scatter(slpt(1,:), slpt(2, :), 20, 'red');
+     scatter(mapt(1,:), mapt(2, :), 20, 'cyan');
+   elseif (N == 3)
+     line([slpt(1,:); mapt(1,:)], [slpt(2,:); mapt(2,:)],  [slpt(3,:); mapt(3,:)], 'Color', 'blue');
+     scatter3(slpt(1,:), slpt(2, :), slpt(3, :), 20, 'red');
+     scatter3(mapt(1,:), mapt(2, :), mapt(3, :), 20, 'cyan');
+   end
+   if (test_case == 0)
+    rectangle('position', [-80, 0, 160, 160], 'Curvature', [1 1]);  % draw the obstacle
+    axis([-15 15 -3 44]);
+   end
+   if (test_case == 3)
+    rectangle('position', [-2, -1, 4, 4], 'Curvature', [1 1]);  % draw the obstacle
+    axis([-1.3 1.3 -1.1 0.8]);
+   end
+   hold off
+ 
+   pause(0.1);
+ 
+   vf = vf * vf_mult; F(N) = -vf;
+   gf_model_set(md, 'variable', 'data1', F);
+   if (test_case ~= 3 && test_case ~= 0)
+     gf_model_set(md, 'variable', 'data2', F);
+   end
+   
+   if (test_case <= 1)
+     Ddata(N) = Ddata(N) - 1;
+     gf_model_set(md, 'variable', 'Ddata', Ddata);
+   end
+   
+ 
+ end;
++>>>>>>> upstream
diff --cc interface/tests/matlab/demo_static_contact.m
index a619561,54025eb..95d22ab
--- a/interface/tests/matlab/demo_static_contact.m
+++ b/interface/tests/matlab/demo_static_contact.m
@@@ -48,8 -48,15 +48,20 @@@ clambda = 1;           % Lame coefficie
  cmu = 1;               % Lame coefficient
  friction_coeff = 0.4;  % coefficient of friction
  vertical_force = 0.05; % Volumic load in the vertical direction
++<<<<<<< HEAD
 +r = 1;                % Augmentation parameter
 +condition_type = 2; % 0 = Explicitely kill horizontal rigid displacements
++=======
+ u_degree = 2;
+ lambda_degree = 2;
+ incompressibility = 0;
+ p_degree = 1;
+ r = 40;                 % Augmentation parameter
+ gamma0 = 1/r;          % Nitsche's method gamma0 parameter
+ theta = 0;             % Nitsche's method theta parameter
+ 
+ condition_type = 0; % 0 = Explicitely kill horizontal rigid displacements
++>>>>>>> upstream
                      % 1 = Kill rigid displacements using a global penalization
                      % 2 = Add a Dirichlet condition on the top of the structure
  penalty_parameter = 1E-6;    % Penalization coefficient for the global penalization
@@@ -63,7 -70,7 +75,11 @@@ end
  
  niter = 100;   % Maximum number of iterations for Newton's algorithm.
  plot_mesh = true;
++<<<<<<< HEAD
 +version = 1;  % 1 : frictionless contact and the basic contact brick
++=======
+ version = 16;  % 1 : frictionless contact and the basic contact brick
++>>>>>>> upstream
                % 2 : contact with 'static' Coulomb friction and basic contact brick
                % 3 : frictionless contact and the contact with a
                %     rigid obstacle brick
@@@ -93,6 -100,8 +109,11 @@@
                %     on the Lagrangian augmented by the penalization term.
                % 15 : penalized contact with 'static' Coulomb friction (r is the penalization
                %     coefficient).
++<<<<<<< HEAD
++=======
+               % 16 : contact without friction and integral Nitsche approach
+               % 17 : contact with friction and integral Nitsche approach
++>>>>>>> upstream
   % Signed distance representing the obstacle
  if (d == 2) obstacle = 'y'; else obstacle = 'z'; end;
  
@@@ -103,25 -112,27 +124,47 @@@ border = gf_mesh_get(m,'outer faces')
  normals = gf_mesh_get(m, 'normal of faces', border);
  contact_boundary=border(:, find(normals(d, :) < -0.01));
  gf_mesh_set(m, 'region', GAMMAC, contact_boundary);
++<<<<<<< HEAD
 +contact_boundary=border(:, find(normals(d, :) > 0.01));
 +gf_mesh_set(m, 'region', GAMMAD, contact_boundary);
++=======
+ dirichlet_boundary=border(:, find(normals(d, :) > 0.01));
+ gf_mesh_set(m, 'region', GAMMAD, dirichlet_boundary);
++>>>>>>> upstream
  
  
  
  
  % Finite element methods
++<<<<<<< HEAD
 +u_degree = 2;
 +lambda_degree = 2;
 +
 +mfu=gf_mesh_fem(m, d);
 +gf_mesh_fem_set(mfu, 'classical fem', u_degree);
 +mfd=gf_mesh_fem(m, 1);
 +gf_mesh_fem_set(mfd, 'classical fem', u_degree);
 +mflambda=gf_mesh_fem(m, 1); % used only by versions 5 to 13
 +gf_mesh_fem_set(mflambda, 'classical fem', lambda_degree);
 +mfvm=gf_mesh_fem(m, 1);
 +gf_mesh_fem_set(mfvm, 'classical discontinuous fem', u_degree-1);
 +
++=======
+ 
+ mfu=gf_mesh_fem(m, d);
+ gf_mesh_fem_set(mfu, 'classical fem', u_degree);
+ if (incompressibility)
+   mfp=gf_mesh_fem(m, 1);
+   gf_mesh_fem_set(mfp, 'classical fem', p_degree);
+ end
+ mfd=gf_mesh_fem(m, 1);
+ gf_mesh_fem_set(mfd, 'classical fem', u_degree);
+ mflambda=gf_mesh_fem(m, 1); % used only by versions 5 to 13
+ gf_mesh_fem_set(mflambda, 'classical fem', lambda_degree);
+ mfvm=gf_mesh_fem(m, 1);
+ gf_mesh_fem_set(mfvm, 'classical discontinuous fem', u_degree-1);
+ 
++>>>>>>> upstream
  % Integration method
  mim=gf_mesh_im(m, 4);
  if (d == 2)
@@@ -153,6 -164,10 +196,13 @@@ gf_model_set(md, 'add initialized data'
  gf_model_set(md, 'add initialized data', 'clambda', [clambda]);
  gf_model_set(md, 'add isotropic linearized elasticity brick', mim, 'u', ...
                   'clambda', 'cmu');
++<<<<<<< HEAD
++=======
+ if (incompressibility)
+   gf_model_set(md, 'add fem variable', 'p', mfp);
+   gf_model_set(md, 'add linear incompressibility brick', mim, 'u', 'p');
+ end
++>>>>>>> upstream
  gf_model_set(md, 'add initialized fem data', 'volumicload', mfd, F);
  gf_model_set(md, 'add source term brick', mim, 'u', 'volumicload');
  
@@@ -323,13 -338,32 +373,39 @@@ elseif (version == 15
    gf_model_set(md, 'add penalized contact with rigid obstacle brick', mim_friction, 'u', ...
  	         'obstacle', 'r', 'friction_coeff', GAMMAC);
      
++<<<<<<< HEAD
++=======
+          
+ elseif (version == 16 || version == 17)
+  
+   gf_model_set(md, 'add initialized data', 'gamma0', [gamma0]);
+   gf_model_set(md, 'add initialized data', 'theta', [theta]);
+   
+   if (version == 16)
+     gf_model_set(md, 'add initialized data', 'friction_coeff', [0]);
+   else
+     gf_model_set(md, 'add initialized data', 'friction_coeff', [friction_coeff]);
+   end
+   OBS = gf_mesh_fem_get(mfd, 'eval', { obstacle });
+   gf_model_set(md, 'add initialized fem data', 'obstacle', mfd, OBS);
+   % gf_model_set(md, 'add Nitsche contact with rigid obstacle brick old', mim_friction, 'u', 'obstacle', 'gamma0', 'theta', 'friction_coeff', 'clambda', 'cmu', GAMMAC);    
+   if (version == 16)
+     gf_model_set(md, 'add Nitsche contact with rigid obstacle brick', mim_friction, 'u', 'obstacle', 'gamma0', GAMMAC, theta);    
+   else
+     gf_model_set(md, 'add Nitsche contact with rigid obstacle brick', mim_friction, 'u', 'obstacle', 'gamma0', GAMMAC, theta, 'friction_coeff'); 
+   end
++>>>>>>> upstream
  else
    error('Inexistent version');
  end
  
  % Solve the problem
  if (~solved)
++<<<<<<< HEAD
 +  gf_model_get(md, 'test tangent matrix', 1e-6, 10, 0.01);
++=======
+   gf_model_get(md, 'test tangent matrix', 1e-6, 10, 0.1);
++>>>>>>> upstream
    gf_model_get(md, 'solve', 'max_res', 1E-9, 'very noisy', 'max_iter', niter); % ,  'lsearch', 'simplest'); % , 'with pseudo potential');
  end;
  
diff --cc src/Makefile.am
index 480eb0f,84161f9..d575747
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@@ -132,6 -132,7 +132,10 @@@ nobase_include_HEADERS 
  	getfem/getfem_model_solvers.h             	\
  	getfem/getfem_linearized_plates.h         	\
  	getfem/getfem_contact_and_friction_common.h	\
++<<<<<<< HEAD
++=======
+ 	getfem/getfem_contact_and_friction_large_sliding.h \
++>>>>>>> upstream
  	getfem/getfem_contact_and_friction_nodal.h	\
  	getfem/getfem_contact_and_friction_integral.h	\
  	getfem/getfem_Coulomb_friction.h          	\
@@@ -140,9 -141,12 +144,15 @@@
  	getfem/getfem_Navier_Stokes.h             	\
  	getfem/getfem_superlu.h		   		\
  	getfem/getfem_plasticity.h                	\
++<<<<<<< HEAD
++=======
+ 	getfem/getfem_omp.h                         \
++>>>>>>> upstream
  	getfem/getfem_continuation.h                    \
  	getfem/getfem_mesher.h                          \
- 	getfem/getfem_convect.h                    	
+ 	getfem/getfem_convect.h                    	\
+ 	getfem/getfem_deformable_mesh.h                 \
+ 	getfem/getfem_level_set_contact.h                   	
  
  SRC =                                      		\
  	dal_backtrace.cc                   		\
@@@ -202,9 -206,14 +212,20 @@@
  	getfem_model_solvers.cc                		\
  	getfem_fourth_order.cc                		\
  	getfem_nonlinear_elasticity.cc                  \
++<<<<<<< HEAD
 +	getfem_contact_and_friction_nodal.cc		\
 +	getfem_contact_and_friction_integral.cc	\
 +	getfem_plasticity.cc				
++=======
+ 	getfem_contact_and_friction_common.cc		\
+ 	getfem_contact_and_friction_nodal.cc		\
+ 	getfem_contact_and_friction_integral.cc	        \
+ 	getfem_contact_and_friction_large_sliding.cc    \
+ 	getfem_plasticity.cc				\
+ 	getfem_omp.cc                       \
+ 	getfem_deformable_mesh.cc			\
+ 	getfem_level_set_contact.cc
++>>>>>>> upstream
  #	getfem_enumeration_dof_para.cc
  
  lib_LTLIBRARIES = libgetfem.la
diff --cc src/bgeot_ftool.cc
index e4ddc38,df15961..5b0418a
--- a/src/bgeot_ftool.cc
+++ b/src/bgeot_ftool.cc
@@@ -24,7 -24,7 +24,11 @@@
  #include "getfem/bgeot_ftool.h"
  #include <ctype.h>
  #include <limits.h>
++<<<<<<< HEAD
 +#ifndef WIN32
++=======
+ #ifndef _WIN32
++>>>>>>> upstream
  #  include <unistd.h>
  #endif
  #include <fstream>
diff --cc src/bgeot_geometric_trans.cc
index 1f44f5e,80d6fce..882dd6e
--- a/src/bgeot_geometric_trans.cc
+++ b/src/bgeot_geometric_trans.cc
@@@ -174,9 -173,7 +173,11 @@@ namespace bgeot 
     const base_matrix& G__) :
      xref_(xref__), G_(&G__), pgt_(pgt__), pgp_(0), pspt_(0),
      ii_(size_type(-1)), J_(-1) {}
++<<<<<<< HEAD
 +
++=======
++>>>>>>> upstream
  
-   typedef dal::naming_system<geometric_trans>::param_list gt_param_list;
  
    base_node geometric_trans::transform(const base_node &pt,
                                         const base_matrix &G) const {
@@@ -217,7 -214,7 +218,11 @@@
      virtual void poly_vector_val(const base_node &pt, base_vector &val) const {
        val.resize(nb_points());
        for (size_type k = 0; k < nb_points(); ++k)
++<<<<<<< HEAD
 +        val[k] = trans[k].eval(pt.begin());
++=======
+         val[k] = to_scalar(trans[k].eval(pt.begin()));
++>>>>>>> upstream
      }
  
      virtual void poly_vector_val(const base_node &pt, const convex_ind_ct &ind_ct,
@@@ -225,7 -222,7 +230,11 @@@
        size_type nb_funcs=ind_ct.size();
        val.resize(nb_funcs);
        for (size_type k = 0; k < nb_funcs; ++k)
++<<<<<<< HEAD
 +        val[k] = trans[ind_ct[k]].eval(pt.begin());
++=======
+         val[k] = to_scalar(trans[ind_ct[k]].eval(pt.begin()));
++>>>>>>> upstream
      }
  
      virtual void poly_vector_grad(const base_node &pt, base_matrix &pc) const {
@@@ -235,11 -232,12 +244,20 @@@
          for (dim_type n = 0; n < dim(); ++n) {
            PP = trans[i];
            PP.derivative(n);
++<<<<<<< HEAD
 +          pc(i, n) = PP.eval(pt.begin());
 +        }
 +    }
 +
 +    virtual void poly_vector_grad(const base_node &pt, const convex_ind_ct &ind_ct,
++=======
+           pc(i, n) = to_scalar(PP.eval(pt.begin()));
+         }
+     }
+ 
+     virtual void poly_vector_grad(const base_node &pt,
+ 				  const convex_ind_ct &ind_ct,
++>>>>>>> upstream
                                    base_matrix &pc) const {
        FUNC PP;
        size_type nb_funcs=ind_ct.size();
@@@ -248,7 -246,7 +266,11 @@@
          for (dim_type n = 0; n < dim(); ++n) {
            PP = trans[ind_ct[i]];
            PP.derivative(n);
++<<<<<<< HEAD
 +          pc(i, n) = PP.eval(pt.begin());
++=======
+           pc(i, n) = to_scalar(PP.eval(pt.begin()));
++>>>>>>> upstream
          }
      }
  
@@@ -260,7 -258,7 +282,11 @@@
            QP = trans[i]; QP.derivative(n);
            for (dim_type m = 0; m <= n; ++m) {
              PP = QP; PP.derivative(m);
++<<<<<<< HEAD
 +            pc(i, n*dim()+m) = pc(i, m*dim()+n) = PP.eval(pt.begin());
++=======
+             pc(i, n*dim()+m) = pc(i, m*dim()+n) = to_scalar(PP.eval(pt.begin()));
++>>>>>>> upstream
            }
          }
      }
@@@ -544,6 -631,12 +659,15 @@@
      }
    };
  
++<<<<<<< HEAD
++=======
+   void add_geometric_trans_name
+     (std::string name, dal::naming_system<geometric_trans>::pfunction f) {
+     dal::singleton<geometric_trans_naming_system>::instance().add_suffix(name,
+ 									 f);
+   }
+ 
++>>>>>>> upstream
    pgeometric_trans geometric_trans_descriptor(std::string name) {
      size_type i=0;
      return dal::singleton<geometric_trans_naming_system>::instance().method(name, i);
diff --cc src/bgeot_poly.cc
index fc7932d,587eb0d..3efe859
--- a/src/bgeot_poly.cc
+++ b/src/bgeot_poly.cc
@@@ -191,7 -191,7 +191,11 @@@ namespace bgeot 
          case 5  : 
  	  {
  	    if (p2.degree() > 0) parse_error(7);
++<<<<<<< HEAD
 +	    int pow = int(p2[0]);
++=======
+ 	    int pow = int(to_scalar(p2[0]));
++>>>>>>> upstream
  	    if (p2[0] !=  opt_long_scalar_type(pow) || pow < 0) parse_error(8);
  	    base_poly p = p1; p1.one();
  	    for (int i = 0; i < pow; ++i) p1 *= p;
diff --cc src/dal_singleton.cc
index 209052d,3401dcf..d05cdc8
--- a/src/dal_singleton.cc
+++ b/src/dal_singleton.cc
@@@ -1,22 -1,22 +1,43 @@@
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2004-2012 Julien Pommier
 + 
 + This file is a part of GETFEM++
 + 
 + Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
 + Exception either version 3.1 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 Lesser General Public
 + License and GCC Runtime Library Exception for more details.
 + You  should  have received a copy of the GNU Lesser General Public License
 + along  with  this program;  if not, write to the Free Software Foundation,
 + Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
 + 
++=======
+ 
+ Copyright (C) 2004-2012 Julien Pommier
+ 
+ This file is a part of GETFEM++
+ 
+ Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
+ Exception either version 3.1 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 Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  #include "getfem/dal_singleton.h"
diff --cc src/dal_static_stored_objects.cc
index a8b71e3,69acbbf..209e881
--- a/src/dal_static_stored_objects.cc
+++ b/src/dal_static_stored_objects.cc
@@@ -1,22 -1,22 +1,43 @@@
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2002-2012 Yves Renard
 + 
 + This file is a part of GETFEM++
 + 
 + Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
 + Exception either version 3.1 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 Lesser General Public
 + License and GCC Runtime Library Exception for more details.
 + You  should  have received a copy of the GNU Lesser General Public License
 + along  with  this program;  if not, write to the Free Software Foundation,
 + Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
 + 
++=======
+ 
+ Copyright (C) 2002-2012 Yves Renard
+ 
+ This file is a part of GETFEM++
+ 
+ Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
+ Exception either version 3.1 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 Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  
diff --cc src/getfem/bgeot_geometric_trans.h
index c50f84e,1735eef..48ad689
--- a/src/getfem/bgeot_geometric_trans.h
+++ b/src/getfem/bgeot_geometric_trans.h
@@@ -213,6 -214,7 +214,10 @@@ namespace bgeot 
                                      pgeometric_trans pg2);
    pgeometric_trans linear_product_geotrans(pgeometric_trans pg1,
                                             pgeometric_trans pg2);
++<<<<<<< HEAD
++=======
+   pgeometric_trans Q2_incomplete_geotrans(dim_type nc);
++>>>>>>> upstream
  
    /**
       Get the geometric transformation from its string name.
@@@ -222,14 -224,16 +227,27 @@@
    /**
       Get the string name of a geometric transformation.
  
++<<<<<<< HEAD
 +  List of possible names:
 +   * GT_PK(N,K)   : Transformation on simplexes, dim N, degree K
 +   * GT_QK(N,K)   : Transformation on parallelepipeds, dim N, degree K
 +   * GT_PRISM(N,K)          : Transformation on prisms, dim N, degree K
 +   * GT_PRODUCT(a,b)        : tensorial product of two transformations
 +   * GT_LINEAR_PRODUCT(a,b) : Linear tensorial product of two transformations
 +   * GT_LINEAR_QK(N) : shortcut for GT_LINEAR_PRODUCT(GT_LINEAR_QK(N-1),
 +   *                                                  GT_PK(1,1))
++=======
+      List of possible names:
+      GT_PK(N,K)   : Transformation on simplexes, dim N, degree K
+      
+      GT_QK(N,K)   : Transformation on parallelepipeds, dim N, degree K
+      GT_PRISM(N,K)          : Transformation on prisms, dim N, degree K
+      GT_Q2_INCOMPLETE(N)    : Q2 incomplete transformation in dim N=2 or 3.
+      GT_PRODUCT(a,b)        : tensorial product of two transformations
+      GT_LINEAR_PRODUCT(a,b) : Linear tensorial product of two transformations
+      GT_LINEAR_QK(N) : shortcut for GT_LINEAR_PRODUCT(GT_LINEAR_QK(N-1),
+                                                       GT_PK(1,1))
++>>>>>>> upstream
     */
  
    std::string name_of_geometric_trans(pgeometric_trans p);
@@@ -333,7 -337,7 +351,11 @@@
           itk != G.end(); ++itk, ++k)
        gmm::add(gmm::scaled(*itk, c[j][k]), pt);
      GMM_ASSERT1(k == pgt->nb_points(),
++<<<<<<< HEAD
 +                "Wrong number of points in tranformation");
++=======
+                 "Wrong number of points in transformation");
++>>>>>>> upstream
    }
  
    template <typename CONT>
diff --cc src/getfem/bgeot_tensor.h
index ce028dc,28a97b6..48f40b8
--- a/src/getfem/bgeot_tensor.h
+++ b/src/getfem/bgeot_tensor.h
@@@ -1,7 -1,7 +1,11 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
   
++<<<<<<< HEAD
 + Copyright (C) 2000-2012 Yves Renard
++=======
+  Copyright (C) 2000-2013 Yves Renard
++>>>>>>> upstream
   
   This file is a part of GETFEM++
   
@@@ -329,4 -340,4 +344,4 @@@ namespace bgeot 
  }  /* end of namespace bgeot.                                              */
  
  
- #endif  /* BGEOT_TENSOR_H__ */
 -#endif  /* BGEOT_TENSOR_H */
++#endif  /* BGEOT_TENSOR_H */
diff --cc src/getfem/dal_naming_system.h
index d8bf5f9,ab6db49..5201b70
--- a/src/getfem/dal_naming_system.h
+++ b/src/getfem/dal_naming_system.h
@@@ -315,7 -316,6 +316,10 @@@ namespace dal 
    {
  
      pmethod pm = 0;
++<<<<<<< HEAD
 +
++=======
++>>>>>>> upstream
  	method_key nname(name);
  	pstatic_stored_object o = search_stored_object(nname);
  
diff --cc src/getfem/dal_singleton.h
index 21de9e1,b13a312..a40da52
--- a/src/getfem/dal_singleton.h
+++ b/src/getfem/dal_singleton.h
@@@ -1,32 -1,32 +1,62 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2004-2012 Julien Pommier
 + 
 + This file is a part of GETFEM++
 + 
 + Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
 + Exception either version 3.1 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 Lesser General Public
 + License and GCC Runtime Library Exception for more details.
 + You  should  have received a copy of the GNU Lesser General Public License
 + along  with  this program;  if not, write to the Free Software Foundation,
 + Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
 + 
 + As a special exception, you  may use  this file  as it is a part of a free
 + software  library  without  restriction.  Specifically,  if   other  files
 + instantiate  templates  or  use macros or inline functions from this file,
 + or  you compile this  file  and  link  it  with other files  to produce an
 + executable, this file  does  not  by itself cause the resulting executable
 + to be covered  by the GNU Lesser General Public License.  This   exception
 + does not  however  invalidate  any  other  reasons why the executable file
 + might be covered by the GNU Lesser General Public License.
 + 
++=======
+ 
+ Copyright (C) 2004-2012 Julien Pommier
+ 
+ This file is a part of GETFEM++
+ 
+ Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
+ Exception either version 3.1 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 Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ 
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  /**@file dal_singleton.h
diff --cc src/getfem/dal_static_stored_objects.h
index 8bc3d73,06e2d8c..8aeaca9
--- a/src/getfem/dal_static_stored_objects.h
+++ b/src/getfem/dal_static_stored_objects.h
@@@ -1,32 -1,32 +1,62 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2002-2012 Yves Renard
 + 
 + This file is a part of GETFEM++
 + 
 + Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
 + Exception either version 3.1 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 Lesser General Public
 + License and GCC Runtime Library Exception for more details.
 + You  should  have received a copy of the GNU Lesser General Public License
 + along  with  this program;  if not, write to the Free Software Foundation,
 + Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
 + 
 + As a special exception, you  may use  this file  as it is a part of a free
 + software  library  without  restriction.  Specifically,  if   other  files
 + instantiate  templates  or  use macros or inline functions from this file,
 + or  you compile this  file  and  link  it  with other files  to produce an
 + executable, this file  does  not  by itself cause the resulting executable
 + to be covered  by the GNU Lesser General Public License.  This   exception
 + does not  however  invalidate  any  other  reasons why the executable file
 + might be covered by the GNU Lesser General Public License.
 + 
++=======
+ 
+ Copyright (C) 2002-2012 Yves Renard
+ 
+ This file is a part of GETFEM++
+ 
+ Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
+ Exception either version 3.1 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 Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ 
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  /** @file dal_static_stored_objects.h 
diff --cc src/getfem/getfem_Coulomb_friction.h
index 8c01dce,6b9cb3c..b15ecd2
--- a/src/getfem/getfem_Coulomb_friction.h
+++ b/src/getfem/getfem_Coulomb_friction.h
@@@ -44,6 -44,7 +44,10 @@@
  
  #include "getfem_contact_and_friction_nodal.h"
  #include "getfem_contact_and_friction_integral.h"
++<<<<<<< HEAD
++=======
+ #include "getfem_contact_and_friction_large_sliding.h"
++>>>>>>> upstream
  
  namespace getfem {
  
@@@ -374,7 -375,7 +378,11 @@@
        gmm::copy(M, AUG_M);
      }
  
++<<<<<<< HEAD
 +    void clear_character_matrix(void) { resize(CH_M, 0, 0); }
++=======
+     void clear_character_matrix(void) { gmm::resize(CH_M, 0, 0); }
++>>>>>>> upstream
      template<typename MAT> void set_character_matrix(const MAT &M) {
        gmm::resize(CH_M, gmm::mat_nrows(M), gmm::mat_ncols(M));
        gmm::copy(M, CH_M);
diff --cc src/getfem/getfem_assembling.h
index 2c0403b,e8602c9..d78dcdd
--- a/src/getfem/getfem_assembling.h
+++ b/src/getfem/getfem_assembling.h
@@@ -42,9 -42,7 +42,12 @@@
  #define GETFEM_ASSEMBLING_H__
  
  #include "getfem_assembling_tensors.h"
 +#include "getfem/getfem_mesh_im_level_set.h"
  
++<<<<<<< HEAD
 +
++=======
++>>>>>>> upstream
  namespace getfem {
    
    template <typename VEC>
diff --cc src/getfem/getfem_assembling_tensors.h
index 9baf53f,3f23ae8..7d8538c
--- a/src/getfem/getfem_assembling_tensors.h
+++ b/src/getfem/getfem_assembling_tensors.h
@@@ -1,7 -1,7 +1,11 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
   
++<<<<<<< HEAD
 + Copyright (C) 2003-2012 Julien Pommier
++=======
+  Copyright (C) 2003-2013 Julien Pommier
++>>>>>>> upstream
   
   This file is a part of GETFEM++
   
diff --cc src/getfem/getfem_contact_and_friction_common.h
index 265a6d2,726e7ac..bd8facd
--- a/src/getfem/getfem_contact_and_friction_common.h
+++ b/src/getfem/getfem_contact_and_friction_common.h
@@@ -1,10 -1,10 +1,18 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2011-2012 Yves Renard, Konstantinos Poulios.
 + 
 + This file is a part of GETFEM++
 + 
++=======
+ 
+  Copyright (C) 2011-2013 Yves Renard, Konstantinos Poulios.
+ 
+  This file is a part of GETFEM++
+ 
++>>>>>>> upstream
   Getfem++  is  free software;  you  can  redistribute  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
@@@ -17,7 -17,7 +25,11 @@@
   You  should  have received a copy of the GNU Lesser General Public License
   along  with  this program;  if not, write to the Free Software Foundation,
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
   As a special exception, you  may use  this file  as it is a part of a free
   software  library  without  restriction.  Specifically,  if   other  files
   instantiate  templates  or  use macros or inline functions from this file,
@@@ -26,7 -26,7 +38,11 @@@
   to be covered  by the GNU Lesser General Public License.  This   exception
   does not  however  invalidate  any  other  reasons why the executable file
   might be covered by the GNU Lesser General Public License.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  /** @file getfem_contact_and_friction_common.h
@@@ -40,6 -40,17 +56,20 @@@
  
  #include "getfem_models.h"
  #include "getfem_assembling_tensors.h"
++<<<<<<< HEAD
++=======
+ #include "getfem/bgeot_rtree.h"
+ #include <getfem/getfem_mesher.h>
+ 
+ 
+ #include <getfem/getfem_arch_config.h>
+ #if GETFEM_HAVE_MUPARSER_MUPARSER_H
+ #include <muParser/muParser.h>
+ #elif GETFEM_HAVE_MUPARSER_H
+ #include <muParser.h>
+ #endif
+ 
++>>>>>>> upstream
  
  namespace getfem {
  
@@@ -50,24 -61,30 +80,51 @@@
    //=========================================================================
  
    template<typename VEC> void ball_projection(const VEC &x,
++<<<<<<< HEAD
 +					      scalar_type radius) {
 +    scalar_type a = gmm::vect_norm2(x);
 +    if (radius <= 0) gmm::clear(const_cast<VEC&>(x));
 +    else if (a > radius) gmm::scale(const_cast<VEC&>(x), radius/a);
 +  }
 +  
 +  template<typename VEC, typename VECR>
 +  void ball_projection_grad_r(const VEC &x, scalar_type radius,
 +                                     VECR &g) {
 +    scalar_type a = gmm::vect_norm2(x);
 +    if (radius > 0 && a >= radius) {
 +      gmm::copy(x, g); gmm::scale(g, scalar_type(1)/a);
 +    }
 +    else gmm::clear(g);
 +  }
 +
 +  template <typename VEC, typename MAT>
 +  void ball_projection_grad(const VEC &x, double radius, MAT &g) {
++=======
+                                               scalar_type radius) {
+     if (radius <= scalar_type(0))
+       gmm::clear(const_cast<VEC&>(x));
+     else {
+       scalar_type a = gmm::vect_norm2(x);
+       if (a > radius) gmm::scale(const_cast<VEC&>(x), radius/a);
+     }
+   }
+ 
+   template<typename VEC, typename VECR>
+   void ball_projection_grad_r(const VEC &x, scalar_type radius,
+                               VECR &g) {
+     if (radius > scalar_type(0)) {
+       scalar_type a = gmm::vect_norm2(x);
+       if (a >= radius) {
+         gmm::copy(x, g); gmm::scale(g, scalar_type(1)/a);
+         return;
+       }
+     }
+     gmm::clear(g);
+   }
+ 
+   template <typename VEC, typename MAT>
+   void ball_projection_grad(const VEC &x, scalar_type radius, MAT &g) {
++>>>>>>> upstream
      if (radius <= scalar_type(0)) { gmm::clear(g); return; }
      gmm::copy(gmm::identity_matrix(), g);
      scalar_type a = gmm::vect_norm2(x);
@@@ -80,6 -97,58 +137,61 @@@
      }
    }
  
++<<<<<<< HEAD
++=======
+   template <typename VEC, typename VECR>
+   void coupled_projection(const VEC &x, const VEC &n,
+                           scalar_type f, VECR &g) {
+     scalar_type xn = gmm::vect_sp(x, n);
+     scalar_type xnm = gmm::neg(xn);
+     scalar_type th = f * xnm;
+     scalar_type xtn = gmm::sqrt(gmm::vect_norm2_sqr(x) - xn*xn);
+ 
+     gmm::copy(gmm::scaled(n, -xnm), g);
+     if (th > scalar_type(0)) {
+       if (xtn <= th) {
+         gmm::add(x, g);
+         gmm::add(gmm::scaled(n, -xn), g);
+       } else {
+         gmm::add(gmm::scaled(x, f*xnm/xtn), g);
+         gmm::add(gmm::scaled(n, -f*xnm*xn/xtn), g);
+       }
+     }
+   }
+ 
+ 
+   template <typename VEC, typename MAT>
+   void coupled_projection_grad(const VEC &x, const VEC &n,
+                                scalar_type f, MAT &g) {
+     scalar_type xn = gmm::vect_sp(x, n);
+     scalar_type xnm = gmm::neg(xn);
+     scalar_type th = f * xnm;
+     scalar_type xtn = gmm::sqrt(gmm::vect_norm2_sqr(x) - xn*xn);
+     size_type N = gmm::vect_size(x);
+     gmm::clear(g);
+ 
+     if (th > scalar_type(0)) {
+       if (xtn <= th) {
+         gmm::copy(gmm::identity_matrix(), g);
+         gmm::rank_one_update(g, gmm::scaled(n, -scalar_type(1)), n);
+       } else if (xn < scalar_type(0)) {
+         static base_small_vector t; gmm::resize(t, N);
+         gmm::add(x, gmm::scaled(n, -xn), t);
+         gmm::scale(t, scalar_type(1)/xtn);
+         if (N > 2) {
+           gmm::copy(gmm::identity_matrix(), g);
+           gmm::rank_one_update(g, gmm::scaled(t, -scalar_type(1)), t);
+           gmm::rank_one_update(g, gmm::scaled(n, -scalar_type(1)), n);
+           gmm::scale(g, -xn*th/xtn);
+         }
+         gmm::rank_one_update(g, gmm::scaled(t, -f), n);
+       }
+     }
+ 
+     if (xn < scalar_type(0)) gmm::rank_one_update(g, n, n);
+   }
+ 
++>>>>>>> upstream
    //=========================================================================
    //
    //  De Saxce projection and its gradients.
@@@ -89,7 -158,7 +201,11 @@@
  
    template<typename VEC>
    void De_Saxce_projection(const VEC &x, const VEC &n_, scalar_type f) {
++<<<<<<< HEAD
 +    static VEC n; // For more robustness, n_ is not supposed unitary
++=======
+     static base_small_vector n; // For more robustness, n_ is not supposed unitary
++>>>>>>> upstream
      size_type N = gmm::vect_size(x);
      gmm::resize(n, N);
      gmm::copy(gmm::scaled(n_, scalar_type(1)/gmm::vect_norm2(n_)), n);
@@@ -107,8 -176,8 +223,13 @@@
  
    template<typename VEC, typename MAT>
    void De_Saxce_projection_grad(const VEC &x, const VEC &n_,
++<<<<<<< HEAD
 +				scalar_type f, MAT &g) {
 +    static VEC n;
++=======
+                                 scalar_type f, MAT &g) {
+     static base_small_vector n;
++>>>>>>> upstream
      size_type N = gmm::vect_size(x);
      gmm::resize(n, N);
      gmm::copy(gmm::scaled(n_, scalar_type(1)/gmm::vect_norm2(n_)), n);
@@@ -119,7 -188,7 +240,11 @@@
      if (xn > scalar_type(0) && f * nxt <= xn) {
        gmm::clear(g);
      } else if (xn > scalar_type(0) || nxt > -f*xn) {
++<<<<<<< HEAD
 +      static VEC xt;
++=======
+       static base_small_vector xt;
++>>>>>>> upstream
        gmm::resize(xt, N);
        gmm::add(x, gmm::scaled(n, -xn), xt);
        gmm::scale(xt, scalar_type(1)/nxt);
@@@ -144,8 -213,8 +269,13 @@@
  
    template<typename VEC, typename MAT>
    static void De_Saxce_projection_gradn(const VEC &x, const VEC &n_,
++<<<<<<< HEAD
 +					scalar_type f, MAT &g) {
 +    static VEC n;
++=======
+                                         scalar_type f, MAT &g) {
+     static base_small_vector n;
++>>>>>>> upstream
      size_type N = gmm::vect_size(x);
      scalar_type nn = gmm::vect_norm2(n_);
      gmm::resize(n, N);
@@@ -155,8 -224,8 +285,13 @@@
      gmm::clear(g);
  
      if (!(xn > scalar_type(0) && f * nxt <= xn)
++<<<<<<< HEAD
 +	&& (xn > scalar_type(0) || nxt > -f*xn)) {
 +      static VEC xt, aux;
++=======
+         && (xn > scalar_type(0) || nxt > -f*xn)) {
+       static base_small_vector xt, aux;
++>>>>>>> upstream
        gmm::resize(xt, N); gmm::resize(aux, N);
        gmm::add(x, gmm::scaled(n, -xn), xt);
        gmm::scale(xt, scalar_type(1)/nxt);
@@@ -170,11 -239,513 +305,520 @@@
  
        gmm::add(gmm::scaled(xt, -f), n, aux);
        gmm::rank_one_update(g, aux, gmm::scaled(xt, (nxt+f*xn)/nn));
++<<<<<<< HEAD
 +     
++=======
+ 
++>>>>>>> upstream
        gmm::scale(g, scalar_type(1) / (f*f+scalar_type(1)));
      }
    }
  
++<<<<<<< HEAD
++=======
+   //=========================================================================
+   //
+   //  Some basic assembly functions.
+   //
+   //=========================================================================
+ 
+   template <typename MAT1, typename MAT2>
+   void mat_elem_assembly(const MAT1 &M_, const MAT2 &Melem,
+                          const mesh_fem &mf1, size_type cv1,
+                          const mesh_fem &mf2, size_type cv2) {
+     MAT1 &M = const_cast<MAT1 &>(M_);
+     typedef typename gmm::linalg_traits<MAT1>::value_type T;
+     T val;
+     mesh_fem::ind_dof_ct cvdof1 = mf1.ind_basic_dof_of_element(cv1);
+     mesh_fem::ind_dof_ct cvdof2 = mf2.ind_basic_dof_of_element(cv2);
+ 
+     GMM_ASSERT1(cvdof1.size() == gmm::mat_nrows(Melem)
+                 && cvdof2.size() == gmm::mat_ncols(Melem),
+                 "Dimensions mismatch");
+ 
+     if (mf1.is_reduced()) {
+       if (mf2.is_reduced()) {
+         for (size_type i = 0; i < cvdof1.size(); ++i)
+           for (size_type j = 0; j < cvdof2.size(); ++j)
+             if ((val = Melem(i,j)) != T(0))
+               asmrankoneupdate
+                 (M, gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
+                  gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
+       } else {
+         for (size_type i = 0; i < cvdof1.size(); ++i)
+           for (size_type j = 0; j < cvdof2.size(); ++j)
+             if ((val = Melem(i,j)) != T(0))
+               asmrankoneupdate
+                 (M, gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
+                  cvdof2[j], val);
+       }
+     } else {
+       if (mf2.is_reduced()) {
+         for (size_type i = 0; i < cvdof1.size(); ++i)
+           for (size_type j = 0; j < cvdof2.size(); ++j)
+             if ((val = Melem(i,j)) != T(0))
+               asmrankoneupdate
+                 (M, cvdof1[i],
+                  gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
+       } else {
+         for (size_type i = 0; i < cvdof1.size(); ++i)
+           for (size_type j = 0; j < cvdof2.size(); ++j)
+             if ((val = Melem(i,j)) != T(0))
+               M(cvdof1[i], cvdof2[j]) += val;
+       }
+     }
+   }
+ 
+ 
+   template <typename VEC1, typename VEC2>
+   void vec_elem_assembly(const VEC1 &V_, const VEC2 &Velem,
+                          const mesh_fem &mf, size_type cv) {
+     VEC1 &V = const_cast<VEC1 &>(V_);
+     typedef typename gmm::linalg_traits<VEC1>::value_type T;
+     std::vector<size_type> cvdof(mf.ind_basic_dof_of_element(cv).begin(),
+                                  mf.ind_basic_dof_of_element(cv).end());
+ 
+     GMM_ASSERT1(cvdof.size() == gmm::vect_size(Velem), "Dimensions mismatch");
+ 
+     if (mf.is_reduced()) {
+       T val;
+       for (size_type i = 0; i < cvdof.size(); ++i)
+         if ((val = Velem[i]) != T(0))
+           gmm::add(gmm::scaled(gmm::mat_row(mf.extension_matrix(), cvdof[i]),
+                                val), V);
+     } else {
+       for (size_type i = 0; i < cvdof.size(); ++i) V[cvdof[i]] += Velem[i];
+     }
+   }
+ 
+   template <typename MAT1, typename MAT2>
+   void mat_elem_assembly(const MAT1 &M_, const gmm::sub_interval &I1,
+                          const gmm::sub_interval &I2,
+                          const MAT2 &Melem,
+                          const mesh_fem &mf1, size_type cv1,
+                          const mesh_fem &mf2, size_type cv2) {
+     MAT1 &M = const_cast<MAT1 &>(M_);
+     typedef typename gmm::linalg_traits<MAT1>::value_type T;
+     T val;
+ 
+     mesh_fem::ind_dof_ct cvdof1 = mf1.ind_basic_dof_of_element(cv1);
+     mesh_fem::ind_dof_ct cvdof2 = mf2.ind_basic_dof_of_element(cv2);
+ 
+     GMM_ASSERT1(cvdof1.size() == gmm::mat_nrows(Melem)
+                 && cvdof2.size() == gmm::mat_ncols(Melem),
+                 "Dimensions mismatch");
+ 
+     if (mf1.is_reduced()) {
+       if (mf2.is_reduced()) {
+         for (size_type i = 0; i < cvdof1.size(); ++i)
+           for (size_type j = 0; j < cvdof2.size(); ++j)
+             if ((val = Melem(i,j)) != T(0))
+               asmrankoneupdate
+                 (gmm::sub_matrix(M, I1, I2),
+                  gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
+                  gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
+       } else {
+         for (size_type i = 0; i < cvdof1.size(); ++i)
+           for (size_type j = 0; j < cvdof2.size(); ++j)
+             if ((val = Melem(i,j)) != T(0))
+               asmrankoneupdate
+                 (gmm::sub_matrix(M, I1, I2),
+                  gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
+                  cvdof2[j], val);
+       }
+     } else {
+       if (mf2.is_reduced()) {
+         for (size_type i = 0; i < cvdof1.size(); ++i)
+           for (size_type j = 0; j < cvdof2.size(); ++j)
+             if ((val = Melem(i,j)) != T(0))
+               asmrankoneupdate
+                 (gmm::sub_matrix(M, I1, I2), cvdof1[i],
+                  gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
+       } else {
+         for (size_type i = 0; i < cvdof1.size(); ++i)
+           for (size_type j = 0; j < cvdof2.size(); ++j)
+             if ((val = Melem(i,j)) != T(0))
+               M(cvdof1[i]+I1.first(), cvdof2[j]+I2.first()) += val;
+       }
+     }
+   }
+ 
+   template <typename VEC1, typename VEC2>
+   void vec_elem_assembly(const VEC1 &V_, const gmm::sub_interval &I,
+                          const VEC2 &Velem, const mesh_fem &mf, size_type cv) {
+     VEC1 &V = const_cast<VEC1 &>(V_);
+     typedef typename gmm::linalg_traits<VEC1>::value_type T;
+     std::vector<size_type> cvdof(mf.ind_basic_dof_of_element(cv).begin(),
+                                  mf.ind_basic_dof_of_element(cv).end());
+ 
+     GMM_ASSERT1(cvdof.size() == gmm::vect_size(Velem), "Dimensions mismatch");
+ 
+     if (mf.is_reduced()) {
+       T val;
+       for (size_type i = 0; i < cvdof.size(); ++i)
+         if ((val = Velem[i]) != T(0))
+           gmm::add(gmm::scaled(gmm::mat_row(mf.extension_matrix(), cvdof[i]),
+                                val), gmm::sub_vector(V, I));
+     } else {
+       for (size_type i = 0; i < cvdof.size(); ++i)
+         V[I.first()+cvdof[i]] += Velem[i];
+     }
+   }
+ 
+ 
+   void vectorize_base_tensor(const base_tensor &t, base_matrix &vt,
+                              size_type ndof, size_type qdim, size_type N);
+ 
+   void vectorize_grad_base_tensor(const base_tensor &t, base_tensor &vt,
+                                   size_type ndof, size_type qdim, size_type N);
+ 
+ 
+   //=========================================================================
+   //
+   //  Structure which stores the contact boundaries, rigid obstacles and
+   //  computes the contact pairs in large sliding/large deformation
+   //
+   //=========================================================================
+ 
+   class multi_contact_frame {
+ 
+     // Structure describing a contact boundary
+     struct contact_boundary {
+       size_type region;            // Boundary number
+       const getfem::mesh_fem *mfu; // F.e.m. for the displacement.
+       const getfem::mesh_fem *mflambda; // F.e.m. for the displacement.
+       const getfem::mesh_im *mim;  // Integration method for the boundary.
+       std::string multname;        // Name of the optional contact stress
+                                    // multiplier when linked to a model.
+       size_type ind_U;             // Index of displacement.
+       size_type ind_lambda;        // Index of multiplier (if any).
+       bool slave;
+       contact_boundary(void) {}
+       contact_boundary(size_type r, const mesh_fem *mf,
+                        const mesh_im &mi, size_type i_U, const mesh_fem *mfl,
+                        size_type i_l = size_type(-1))
+         : region(r), mfu(mf), mflambda(mfl), mim(&mi),
+           ind_U(i_U), ind_lambda(i_l), slave(false) {}
+     };
+ 
+ 
+     size_type N;          // Meshes dimensions
+     bool self_contact;    // Self-contact is searched or not.
+     bool ref_conf;        // Contact in reference configuration
+                           // for linear elasticity small sliding contact.
+     bool use_delaunay;    // Use delaunay to detect the contact pairs instead
+                           // of influence boxes.
+     int nodes_mode;       // 0 = Use Gauss points for both slave and master
+                           // 1 = Use finite element nodes for slave and
+                           //     Gauss points for master.
+                           // 2 = Use finite element nodes for both slave
+                           //     and master
+     bool raytrace;        // Use raytrace instead of projection.
+ 
+     scalar_type release_distance;  // Limit distance beyond which the contact
+     // will not be considered. CAUTION: should be comparable to the element
+     // size (if it is too large, a too large set of influence boxes will be
+     // detected and the computation will be slow, except for delaunay option)
+ 
+     scalar_type cut_angle; // Cut angle (in radian) for normal cones
+     scalar_type EPS;       // Should be typically hmin/1000 (for computing
+                            // gradients with finite differences
+     const model *md;       // The model if the structure is linked to a model.
+ 
+     typedef model_real_plain_vector VECTOR;
+     std::vector<const VECTOR *> Us;  // Displacement vectors
+     std::vector<const VECTOR *> Ws;  // "Velocity" vectors
+     std::vector<std::string> Unames; // Displacement vectors names.
+     std::vector<std::string> Wnames; // "Velocity" vectors names.
+     std::vector<VECTOR> ext_Us;      // Unreduced displacement vectors
+     std::vector<VECTOR> ext_Ws;      // Unreduced "velocity" vectors
+     std::vector<const VECTOR *> lambdas;  // Displacement vectors
+     std::vector<std::string> lambdanames; // Displacement vectors names.
+     std::vector<VECTOR> ext_lambdas;      // Unreduced displacement vectors
+ 
+     std::vector<contact_boundary> contact_boundaries;
+ 
+     std::vector<std::string> coordinates;
+     base_node pt_eval;
+ #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
+     std::vector<mu::Parser> obstacles_parsers;
+ #endif
+     std::vector<std::string> obstacles;
+     std::vector<std::string> obstacles_velocities;
+ 
+ 
+     struct normal_cone : public std::vector<base_small_vector> {
+ 
+       void add_normal(const base_small_vector &n)
+       { std::vector<base_small_vector>::push_back(n);}
+       normal_cone(void) {}
+       normal_cone(const base_small_vector &n)
+         : std::vector<base_small_vector>(1, n) { }
+     };
+ 
+     //
+     // Influence boxes
+     //
+     struct influence_box {     // Additional information for an influence box
+       size_type ind_boundary;  // Boundary number
+       size_type ind_element;   // Element number
+       short_type ind_face;     // Face number in element
+       base_small_vector mean_normal;   // Mean outward normal unit vector
+       influence_box(void) {}
+       influence_box(size_type ib, size_type ie,
+                     short_type iff, const base_small_vector &n)
+         : ind_boundary(ib), ind_element(ie), ind_face(iff), mean_normal(n) {}
+     };
+ 
+     bgeot::rtree element_boxes;                  // influence boxes
+     std::vector<influence_box> element_boxes_info;
+ 
+     //
+     // Stored points (for Delaunay and slave nodal boundaries)
+     //
+ 
+     struct boundary_point {    // Additional information for a boundary point
+       base_node ref_point;     // Point coordinate in reference configuration
+       size_type ind_boundary;  // Boundary number
+       size_type ind_element;   // Element number
+       short_type ind_face;     // Face number in element
+       size_type ind_pt;        // Dof number for fem nodes or point number
+                                // of integration method (depending on nodes_mode)
+       normal_cone normals;     // Set of outward unit normal vectors
+       boundary_point(void) {}
+       boundary_point(const base_node &rp, size_type ib, size_type ie,
+                      short_type iff, size_type id, const base_small_vector &n)
+         : ref_point(rp), ind_boundary(ib), ind_element(ie), ind_face(iff),
+           ind_pt(id), normals(n) {}
+     };
+ 
+     std::vector<base_node> boundary_points;
+     std::vector<boundary_point> boundary_points_info;
+ 
+ 
+     size_type add_U(const model_real_plain_vector *U, const std::string &name,
+                     const model_real_plain_vector *w, const std::string &wname);
+     size_type add_lambda(const model_real_plain_vector *lambda,
+                          const std::string &name);
+ 
+     void extend_vectors(void);
+ 
+     void normal_cone_simplicication(void);
+ 
+     bool test_normal_cones_compatibility(const normal_cone &nc1,
+                                          const normal_cone &nc2);
+ 
+     bool test_normal_cones_compatibility(const base_small_vector &n,
+                                          const normal_cone &nc2);
+ 
+     dal::bit_vector aux_dof_cv; // An auxiliary variable for are_dof_linked
+     // function (in order to be of constant complexity).
+ 
+     bool are_dof_linked(size_type ib1, size_type idof1,
+                         size_type ib2, size_type idof2);
+ 
+     bool is_dof_linked(size_type ib1, size_type idof1,
+                        size_type ib2, size_type cv);
+   public:
+ 
+     struct face_info {
+       size_type ind_boundary;
+       size_type ind_element;
+       short_type ind_face;
+       face_info(void) {}
+       face_info(size_type ib, size_type ie, short_type iff)
+         : ind_boundary(ib), ind_element(ie), ind_face(iff) {}
+     };
+ 
+   protected:
+ 
+     std::vector<std::vector<face_info> > potential_pairs;
+ 
+     void add_potential_contact_face(size_type ip, size_type ib, size_type ie,
+                                     short_type iff);
+   public:
+ 
+     // stored information for contact pair
+     struct contact_pair {
+ 
+       base_node slave_point;         // The transformed slave point
+       base_small_vector slave_n;     // Normal unit vector to slave surface
+       size_type slave_ind_boundary;  // Boundary number
+       size_type slave_ind_element;   // Element number
+       short_type slave_ind_face;     // Face number in element
+       size_type slave_ind_pt;        // Dof number for fem nodes or point number
+                                      // of integration method (depending on nodes_mode)
+ 
+       base_node master_point_ref;    // The master point on ref element
+       base_node master_point;        // The transformed master point
+       base_small_vector master_n;    // Normal unit vector to master surface
+       size_type master_ind_boundary; // Boundary number
+       size_type master_ind_element;  // Element number
+       short_type master_ind_face;    // Face number in element
+ 
+       scalar_type signed_dist;
+ 
+       size_type irigid_obstacle;
+ 
+       contact_pair(void) {}
+       contact_pair(const base_node &spt, const base_small_vector &nx,
+                    const boundary_point &bp,
+                    const base_node &mptr,  const base_node &mpt,
+                    const base_small_vector &ny,
+                    const face_info &mfi, scalar_type sd)
+         : slave_point(spt), slave_n(nx),
+           slave_ind_boundary(bp.ind_boundary), slave_ind_element(bp.ind_element),
+           slave_ind_face(bp.ind_face), slave_ind_pt(bp.ind_pt),
+           master_point_ref(mptr), master_point(mpt), master_n(ny),
+           master_ind_boundary(mfi.ind_boundary), master_ind_element(mfi.ind_element),
+           master_ind_face(mfi.ind_face),
+           signed_dist(sd), irigid_obstacle(-1) {}
+       contact_pair(const base_node &spt, const base_small_vector &nx,
+                    const boundary_point &bp,
+                    const base_node &mpt, const base_small_vector &ny,
+                    size_type ir, scalar_type sd)
+         : slave_point(spt), slave_n(nx), slave_ind_boundary(bp.ind_boundary),
+           slave_ind_element(bp.ind_element), slave_ind_face(bp.ind_face),
+           slave_ind_pt(bp.ind_pt), master_point(mpt), master_n(ny),
+           signed_dist(sd),
+           irigid_obstacle(ir) {}
+ 
+     };
+ 
+ 
+     // Compute the influence boxes of master boundary elements. To be run
+     // before the detection of contact pairs. The influence box is the
+     // bounding box extended by a distance equal to the release distance.
+     void compute_influence_boxes(void);
+ 
+     // For delaunay triangulation. Advantages compared to influence boxes:
+     // No degeneration of the algorithm complexity with refinement and
+     // more easy to extend to fictitious domain with contact.
+     // Stores all the boundary deformed points relatively to
+     // an integration method or to finite element nodes (depending on
+     // nodes_mode). Storing sufficient information to perform
+     // a Delaunay triangulation and to be able to recover the boundary
+     // number, element number, face number, unit normal vector ...
+     void compute_boundary_points(bool slave_only = false);
+     void compute_potential_contact_pairs_delaunay(void);
+     void compute_potential_contact_pairs_influence_boxes(void);
+ 
+   protected:
+ 
+     std::vector<contact_pair> contact_pairs;
+ 
+     void clear_aux_info(void); // Delete auxiliary information
+ 
+   public:
+ 
+     size_type dim(void) const { return N; }
+     const std::vector<contact_pair> &ct_pairs(void) const
+     { return contact_pairs; }
+ 
+ 
+     const getfem::mesh_fem &mfdisp_of_boundary(size_type n) const
+     { return *(contact_boundaries[n].mfu); }
+     const getfem::mesh_fem &mfmult_of_boundary(size_type n) const
+     { return *(contact_boundaries[n].mflambda); }
+     const getfem::mesh_im  &mim_of_boundary(size_type n) const
+     { return *(contact_boundaries[n].mim); }
+     size_type nb_variables(void) const { return Us.size(); }
+     size_type nb_multipliers(void) const { return lambdas.size(); }
+     const std::string &varname(size_type i) const { return Unames[i]; }
+     const std::string &multname(size_type i) const { return lambdanames[i]; }
+     const model_real_plain_vector &disp_of_boundary(size_type n) const
+     { return ext_Us[contact_boundaries[n].ind_U]; }
+     const model_real_plain_vector &w_of_boundary(size_type n) const
+     { return ext_Ws[contact_boundaries[n].ind_U]; }
+     const model_real_plain_vector &mult_of_boundary(size_type n) const
+     { return ext_lambdas[contact_boundaries[n].ind_lambda]; }
+     size_type region_of_boundary(size_type n) const
+     { return contact_boundaries[n].region; }
+     const std::string &varname_of_boundary(size_type n) const
+     { return Unames[contact_boundaries[n].ind_U]; }
+     size_type ind_varname_of_boundary(size_type n) const
+     { return contact_boundaries[n].ind_U; }
+     const std::string &multname_of_boundary(size_type n) const {
+       static const std::string vname;
+       size_type ind = contact_boundaries[n].ind_lambda;
+       return (ind == size_type(-1)) ? vname : lambdanames[ind];
+     }
+     size_type ind_multname_of_boundary(size_type n) const
+     { return contact_boundaries[n].ind_lambda; }
+     size_type nb_boundaries(void) const { return contact_boundaries.size(); }
+     bool is_self_contact(void) const { return self_contact; }
+     bool is_slave_boundary(size_type n) const { return contact_boundaries[n].slave; }
+     void set_raytrace(bool b) { raytrace = b; }
+     void set_nodes_mode(int m) { nodes_mode = m; }
+     size_type nb_contact_pairs(void) const { return contact_pairs.size(); }
+     const contact_pair &get_contact_pair(size_type i)
+     { return contact_pairs[i]; }
+ 
+     multi_contact_frame(size_type NN, scalar_type r_dist,
+                         bool dela = true, bool selfc = true,
+                         scalar_type cut_a = 0.3, bool rayt = false,
+                         int fem_nodes = 0, bool refc = false);
+     multi_contact_frame(const model &md, size_type NN, scalar_type r_dist,
+                         bool dela = true, bool selfc = true,
+                         scalar_type cut_a = 0.3, bool rayt = false,
+                         int fem_nodes = 0, bool refc = false);
+ 
+     size_type add_obstacle(const std::string &obs);
+ 
+     size_type add_slave_boundary(const getfem::mesh_im &mim,
+                                  const getfem::mesh_fem *mfu,
+                                  const model_real_plain_vector *U,
+                                  size_type reg,
+                                  const getfem::mesh_fem *mflambda = 0,
+                                  const model_real_plain_vector *lambda = 0,
+                                  const model_real_plain_vector *w = 0,
+                                  const std::string &varname = std::string(),
+                                  const std::string &multname = std::string(),
+                                  const std::string &wname = std::string());
+ 
+     size_type add_slave_boundary(const getfem::mesh_im &mim, size_type reg,
+                                  const std::string &varname,
+                                  const std::string &multname = std::string(),
+                                  const std::string &wname = std::string());
+ 
+ 
+     size_type add_master_boundary(const getfem::mesh_im &mim,
+                                   const getfem::mesh_fem *mfu,
+                                   const model_real_plain_vector *U,
+                                   size_type reg,
+                                   const getfem::mesh_fem *mflambda = 0,
+                                   const model_real_plain_vector *lambda = 0,
+                                   const model_real_plain_vector *w = 0,
+                                   const std::string &varname = std::string(),
+                                   const std::string &multname = std::string(),
+                                   const std::string &wname = std::string());
+ 
+     size_type add_master_boundary(const getfem::mesh_im &mim, size_type reg,
+                                   const std::string &varname,
+                                   const std::string &multname = std::string(),
+                                   const std::string &wname = std::string());
+ 
+ 
+ 
+     // The whole process of the computation of contact pairs
+     // Contact pairs are seached for a certain boundary (master or slave,
+     // depending on the contact algorithm) on the master ones. If contact pairs
+     // are searched for a master boundary, self-contact is taken into account
+     // if the flag 'self_contact' is set to 'true'. Self-contact is never taken
+     // into account for a slave boundary.
+     void compute_contact_pairs(void);
+ 
+   };
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
++>>>>>>> upstream
  
  }  /* end of namespace getfem.                                             */
  
diff --cc src/getfem/getfem_contact_and_friction_integral.h
index 58b23e8,061e410..d8e8b22
--- a/src/getfem/getfem_contact_and_friction_integral.h
+++ b/src/getfem/getfem_contact_and_friction_integral.h
@@@ -1,10 -1,10 +1,18 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2011-2012 Yves Renard, Konstantinos Poulios.
 + 
 + This file is a part of GETFEM++
 + 
++=======
+ 
+  Copyright (C) 2011-2013 Yves Renard, Konstantinos Poulios.
+ 
+  This file is a part of GETFEM++
+ 
++>>>>>>> upstream
   Getfem++  is  free software;  you  can  redistribute  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
@@@ -17,7 -17,7 +25,11 @@@
   You  should  have received a copy of the GNU Lesser General Public License
   along  with  this program;  if not, write to the Free Software Foundation,
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
   As a special exception, you  may use  this file  as it is a part of a free
   software  library  without  restriction.  Specifically,  if   other  files
   instantiate  templates  or  use macros or inline functions from this file,
@@@ -26,7 -26,7 +38,11 @@@
   to be covered  by the GNU Lesser General Public License.  This   exception
   does not  however  invalidate  any  other  reasons why the executable file
   might be covered by the GNU Lesser General Public License.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  /** @file getfem_contact_and_friction_integral.h
@@@ -45,12 -45,11 +61,20 @@@ namespace getfem 
  
  
    /** Add a frictionless contact condition with a rigid obstacle
++<<<<<<< HEAD
 +      to the model. This brick adds a contact which is defined
 +      in an integral way. It is the direct approximation of an augmented
 +      Lagrangian formulation (see Getfem user documentation) defined at the
 +      continuous level. The advantage should be a better scalability:
 +      the number of
 +      Newton iterations should be more or less independent of the mesh size.
++=======
+       to the model, which is defined in an integral way. It is the direct
+       approximation of an augmented  Lagrangian formulation (see Getfem user
+       documentation) defined at the continuous level. The advantage should be
+       a better scalability: the number of Newton iterations should be more or
+       less independent of the mesh size.
++>>>>>>> upstream
        The condition is applied on the variable `varname_u`
        on the boundary corresponding to `region`. The rigid obstacle should
        be described with the data `dataname_obstacle` being a signed distance to
@@@ -61,8 -60,8 +85,13 @@@
        range of acceptable values.
        Possible values for `option` is 1 for the non-symmetric Alart-Curnier
        augmented Lagrangian method, 2 for the symmetric one, 3 for the
++<<<<<<< HEAD
 +      non-symmetric Alart-Curnier method with an additional augmentation
 +      and 4 for a new unsymmetric method. The default value is 1.
++=======
+       non-symmetric Alart-Curnier method with an additional augmentation.
+       The default value is 1.
++>>>>>>> upstream
    */
    size_type add_integral_contact_with_rigid_obstacle_brick
    (model &md, const mesh_im &mim, const std::string &varname_u,
@@@ -70,12 -69,11 +99,20 @@@
     const std::string &dataname_r, size_type region, int option = 1);
  
    /** Add a contact with friction condition with a rigid obstacle
++<<<<<<< HEAD
 +      to the model. This brick adds a contact which is defined
 +      in an integral way. It is the direct approximation of an augmented
 +      Lagrangian formulation (see Getfem user documentation) defined at the
 +      continuous level. The advantage should be a better scalability:
 +      the number of the
 +      Newton iterations should be more or less independent of the mesh size.
++=======
+       to the model, which is defined in an integral way. It is the direct
+       approximation of an augmented  Lagrangian formulation (see Getfem user
+       documentation) defined at the continuous level. The advantage should be
+       a better scalability: the number of Newton iterations should be more or
+       less independent of the mesh size.
++>>>>>>> upstream
        The condition is applied on the variable `varname_u`
        on the boundary corresponding to `region`. The rigid obstacle should
        be described with the data `dataname_obstacle` being a signed distance
@@@ -84,13 -82,18 +121,27 @@@
        friction stress.
        An inf-sup condition between `multname` and `varname_u` is required.
        The augmentation parameter `dataname_r` should be chosen in a
++<<<<<<< HEAD
 +      range of acceptable values. `dataname_friction_coeff` is the friction
 +      coefficient which could be constant or defined on a finite element
 +      method.
++=======
+       range of acceptable values.
+       The parameter `dataname_friction_coeffs` contains the Coulomb friction
+       coefficient and optionally an adhesional shear stress threshold and the
+       tresca limit shear stress. For constant coefficients its size is from
+       1 to 3. For coefficients described on a finite element method, this
+       vector contains a number of single values, value pairs or triplets
+       equal to the number of the corresponding mesh_fem's basic dofs.
++>>>>>>> upstream
        Possible values for `option` is 1 for the non-symmetric Alart-Curnier
        augmented Lagrangian method, 2 for the symmetric one, 3 for the
        non-symmetric Alart-Curnier method with an additional augmentation
        and 4 for a new unsymmetric method. The default value is 1.
++<<<<<<< HEAD
++=======
+       (Option 4 ignores any adhesional stress and tresca limit coefficients.)
++>>>>>>> upstream
        `dataname_alpha` and `dataname_wt` are optional parameters to solve
        evolutionary friction problems. `dataname_gamma` and `dataname_vt`
        represent optional data for adding a parameter-dependent sliding
@@@ -99,7 -102,7 +150,11 @@@
    size_type add_integral_contact_with_rigid_obstacle_brick
    (model &md, const mesh_im &mim, const std::string &varname_u,
     const std::string &multname, const std::string &dataname_obs,
++<<<<<<< HEAD
 +   const std::string &dataname_r, const std::string &dataname_friction_coeff,
++=======
+    const std::string &dataname_r, const std::string &dataname_friction_coeffs,
++>>>>>>> upstream
     size_type region, int option = 1, const std::string &dataname_alpha = "",
     const std::string &dataname_wt = "",
     const std::string &dataname_gamma = "",
@@@ -123,7 -126,7 +178,11 @@@
    size_type add_penalized_contact_with_rigid_obstacle_brick
    (model &md, const mesh_im &mim, const std::string &varname_u,
     const std::string &dataname_obs, const std::string &dataname_r,
++<<<<<<< HEAD
 +   size_type region, int option = 1, const std::string &dataname_n = "");
++=======
+    size_type region, int option = 1, const std::string &dataname_lambda_n = "");
++>>>>>>> upstream
  
    /** Add a penalized contact condition with Coulomb friction with a
        rigid obstacle to the model.
@@@ -131,8 -134,12 +190,17 @@@
        on the boundary corresponding to `region`. The rigid obstacle should
        be described with the data `dataname_obstacle` being a signed distance to
        the obstacle (interpolated on a finite element method).
++<<<<<<< HEAD
 +      `dataname_friction_coeff`` is the friction coefficient which could
 +      be constant or defined on a finite element method.
++=======
+       The parameter `dataname_friction_coeffs` contains the Coulomb friction
+       coefficient and optionally an adhesional shear stress threshold and the
+       tresca limit shear stress. For constant coefficients its size is from
+       1 to 3. For coefficients described on a finite element method, this
+       vector contains a number of single values, value pairs or triplets
+       equal to the number of the corresponding mesh_fem's basic dofs.
++>>>>>>> upstream
        The penalization parameter `dataname_r` should be chosen
        large enough to prescribe approximate non-penetration and friction
        conditions but not too large not to deteriorate too much the
@@@ -147,7 -154,7 +215,11 @@@
    size_type add_penalized_contact_with_rigid_obstacle_brick
    (model &md, const mesh_im &mim, const std::string &varname_u,
     const std::string &dataname_obs, const std::string &dataname_r,
++<<<<<<< HEAD
 +   const std::string &dataname_friction_coeff,
++=======
+    const std::string &dataname_friction_coeffs,
++>>>>>>> upstream
     size_type region, int option = 1, const std::string &dataname_lambda = "",
     const std::string &dataname_alpha = "",
     const std::string &dataname_wt = "");
@@@ -169,8 -176,8 +241,13 @@@
        range of acceptable values.
        Possible values for `option` is 1 for the non-symmetric Alart-Curnier
        augmented Lagrangian method, 2 for the symmetric one, 3 for the
++<<<<<<< HEAD
 +      non-symmetric Alart-Curnier method with an additional augmentation
 +      and 4 for a new unsymmetric method. The default value is 1.
++=======
+       non-symmetric Alart-Curnier method with an additional augmentation.
+       The default value is 1.
++>>>>>>> upstream
    */
    size_type add_integral_contact_between_nonmatching_meshes_brick
    (model &md, const mesh_im &mim, const std::string &varname_u1,
@@@ -192,20 -199,26 +269,39 @@@
        An inf-sup condition between `multname` and `varname_u1` and
        `varname_u2` is required.
        The augmentation parameter `dataname_r` should be chosen in a
++<<<<<<< HEAD
 +      range of acceptable values. `dataname_friction_coeff` is the friction
 +      coefficient which could be constant or defined on a finite element
 +      method on the same mesh as `varname_u1`.
++=======
+       range of acceptable values.
+       The parameter `dataname_friction_coeffs` contains the Coulomb friction
+       coefficient and optionally an adhesional shear stress threshold and the
+       tresca limit shear stress. For constant coefficients its size is from
+       1 to 3. For coefficients described on a finite element method on the
+       same mesh as `varname_u1`, this vector contains a number of single
+       values, value pairs or triplets equal to the number of the
+       corresponding mesh_fem's basic dofs.
++>>>>>>> upstream
        Possible values for `option` is 1 for the non-symmetric Alart-Curnier
        augmented Lagrangian method, 2 for the symmetric one, 3 for the
        non-symmetric Alart-Curnier method with an additional augmentation
        and 4 for a new unsymmetric method. The default value is 1.
++<<<<<<< HEAD
++=======
+       (Option 4 ignores any adhesional stress and tresca limit coefficients.)
++>>>>>>> upstream
        `dataname_alpha`, `dataname_wt1` and `dataname_wt2` are optional
        parameters to solve evolutionary friction problems.
    */
    size_type add_integral_contact_between_nonmatching_meshes_brick
    (model &md, const mesh_im &mim, const std::string &varname_u1,
     const std::string &varname_u2, const std::string &multname,
++<<<<<<< HEAD
 +   const std::string &dataname_r, const std::string &dataname_friction_coeff,
++=======
+    const std::string &dataname_r, const std::string &dataname_friction_coeffs,
++>>>>>>> upstream
     size_type region1, size_type region2, int option = 1,
     const std::string &dataname_alpha = "",
     const std::string &dataname_wt1 = "",
@@@ -228,7 -241,7 +324,11 @@@
    (model &md, const mesh_im &mim, const std::string &varname_u1,
     const std::string &varname_u2, const std::string &dataname_r,
     size_type region1, size_type region2,
++<<<<<<< HEAD
 +   int option = 1, const std::string &dataname_n = "");
++=======
+    int option = 1, const std::string &dataname_lambda_n = "");
++>>>>>>> upstream
  
  
    /** Add a penalized contact condition with Coulomb friction between
@@@ -239,8 -252,13 +339,18 @@@
        large enough to prescribe approximate non-penetration and friction
        conditions but not too large not to deteriorate too much the
        conditionning of the tangent system.
++<<<<<<< HEAD
 +      `dataname_friction_coeff` is the friction coefficient which could be constant
 +      or defined on a finite element method on the same mesh as `varname_u1`.
++=======
+       The parameter `dataname_friction_coeffs` contains the Coulomb friction
+       coefficient and optionally an adhesional shear stress threshold and the
+       tresca limit shear stress. For constant coefficients its size is from
+       1 to 3. For coefficients described on a finite element method on the
+       same mesh as `varname_u1`, this vector contains a number of single
+       values, value pairs or triplets equal to the number of the
+       corresponding mesh_fem's basic dofs.
++>>>>>>> upstream
        `dataname_lambda` is an optional parameter used if option
        is 2. In that case, the penalization term is shifted by lambda (this
        allows the use of an Uzawa algorithm on the corresponding augmented
@@@ -251,7 -269,7 +361,11 @@@
    size_type add_penalized_contact_between_nonmatching_meshes_brick
    (model &md, const mesh_im &mim, const std::string &varname_u1,
     const std::string &varname_u2, const std::string &dataname_r,
++<<<<<<< HEAD
 +   const std::string &dataname_friction_coeff,
++=======
+    const std::string &dataname_friction_coeffs,
++>>>>>>> upstream
     size_type region1, size_type region2, int option = 1,
     const std::string &dataname_lambda = "",
     const std::string &dataname_alpha = "",
@@@ -265,6 -283,7 +379,10 @@@
                                           K_LL_V2,
                                           UZAWA_PROJ,
                                           CONTACT_FLAG,
++<<<<<<< HEAD
++=======
+                                          CONTACT_PRESSURE,
++>>>>>>> upstream
  
                                           RHS_U_V1,
                                           RHS_U_V2,
@@@ -282,13 -301,12 +400,20 @@@
                                           K_UL_V1,
                                           K_UL_V2,
                                           K_UL_V3,
++<<<<<<< HEAD
 +                                         K_UL_V4,
++=======
++>>>>>>> upstream
                                           UZAWA_PROJ_FRICT,
                                           UZAWA_PROJ_FRICT_SAXCE,
  
                                           K_UU_V1,
                                           K_UU_V2,
++<<<<<<< HEAD
 +                                         K_UL_FRICT_V1, // EYE
++=======
+                                          K_UL_FRICT_V1, // negative EYE
++>>>>>>> upstream
                                           K_UL_FRICT_V2,
                                           K_UL_FRICT_V3,
                                           K_UL_FRICT_V4,
@@@ -319,7 -337,10 +444,14 @@@
                                 // elastic body surface moves outwards)
      base_small_vector no;      // surface normal, pointing outwards with respect
                                 // to the (first) elastic body
++<<<<<<< HEAD
 +    scalar_type g, f_coeff;    // gap and coefficient of friction values
++=======
+     scalar_type g;             // gap value
+     scalar_type f_coeff;       // coefficient of friction value
+     scalar_type tau_adh;       // adhesional shear resistance of the interface
+     scalar_type tresca_lim;    // tresca shear limit for the interface
++>>>>>>> upstream
  
      // these variables are used as temporary storage and they will usually contain
      // garbage from previous calculations
@@@ -340,12 -361,16 +472,23 @@@
      contact_nonlinear_term(dim_type N_, size_type option_, scalar_type r_,
                             bool contact_only_ = true,
                             scalar_type alpha_ = scalar_type(1)) :
++<<<<<<< HEAD
++=======
+       tau_adh(0), tresca_lim(gmm::default_max(scalar_type())),
++>>>>>>> upstream
        N(N_), option(option_), r(r_), contact_only(contact_only_), alpha(alpha_) {
  
        adjust_tensor_size();
      }
  
++<<<<<<< HEAD
 +    const bgeot::multi_index &sizes() const { return sizes_; }
++=======
+     const bgeot::multi_index &sizes(size_type) const { return sizes_; }
+ 
+     virtual void friction_law(scalar_type p, scalar_type &tau);
+     virtual void friction_law(scalar_type p, scalar_type &tau, scalar_type &tau_grad);
++>>>>>>> upstream
  
      virtual void compute(fem_interpolation_context&, bgeot::base_tensor &t);
      virtual void prepare(fem_interpolation_context& /*ctx*/, size_type /*nb*/)
@@@ -368,7 -393,7 +511,11 @@@
      const mesh_fem &mf_obs;     // mandatory
      const mesh_fem *pmf_lambda; // optional for terms involving lagrange multipliers
      const mesh_fem *pmf_coeff;  // optional for terms involving fem described coefficient of friction
++<<<<<<< HEAD
 +    base_vector U, obs, lambda, friction_coeff, WT, VT;
++=======
+     base_vector U, obs, lambda, friction_coeff, tau_adhesion, tresca_limit, WT, VT;
++>>>>>>> upstream
      scalar_type gamma;
  
      template <typename VECT1>
@@@ -377,33 -402,50 +524,75 @@@
       const mesh_fem &mf_u_, const VECT1 &U_,
       const mesh_fem &mf_obs_, const VECT1 &obs_,
       const mesh_fem *pmf_lambda_ = 0, const VECT1 *lambda_ = 0,
++<<<<<<< HEAD
 +     const mesh_fem *pmf_coeff_ = 0, const VECT1 *f_coeff_ = 0,
++=======
+      const mesh_fem *pmf_coeff_ = 0, const VECT1 *f_coeffs_ = 0,
++>>>>>>> upstream
       scalar_type alpha_ = scalar_type(1), const VECT1 *WT_ = 0,
       scalar_type gamma_ = scalar_type(1), const VECT1 *VT_ = 0
      )
        : contact_nonlinear_term(mf_u_.linked_mesh().dim(), option_, r_,
++<<<<<<< HEAD
 +                               (f_coeff_ == 0), alpha_
 +                              ),
 +        mf_u(mf_u_), mf_obs(mf_obs_),
 +        pmf_lambda(pmf_lambda_), pmf_coeff(pmf_coeff_), 
 +        U(mf_u.nb_basic_dof()), obs(mf_obs.nb_basic_dof()),
 +        lambda(0), friction_coeff(0), WT(0), VT(0), gamma(gamma_)
++=======
+                                (f_coeffs_ == 0), alpha_
+                               ),
+         mf_u(mf_u_), mf_obs(mf_obs_),
+         pmf_lambda(pmf_lambda_), pmf_coeff(pmf_coeff_),
+         U(mf_u.nb_basic_dof()), obs(mf_obs.nb_basic_dof()),
+         lambda(0), friction_coeff(0), tau_adhesion(0), tresca_limit(0),
+         WT(0), VT(0), gamma(gamma_)
++>>>>>>> upstream
      {
  
        mf_u.extend_vector(U_, U);
        mf_obs.extend_vector(obs_, obs);
  
        if (pmf_lambda) {
++<<<<<<< HEAD
 +        lambda.resize(pmf_lambda->nb_basic_dof()); 
++=======
+         lambda.resize(pmf_lambda->nb_basic_dof());
++>>>>>>> upstream
          pmf_lambda->extend_vector(*lambda_, lambda);
        }
  
        if (!contact_only) {
++<<<<<<< HEAD
 +        if (!pmf_coeff)
 +          f_coeff = (*f_coeff_)[0];
 +        else {
 +          friction_coeff.resize(pmf_coeff->nb_basic_dof());
 +          pmf_coeff->extend_vector(*f_coeff_, friction_coeff);
++=======
+         if (!pmf_coeff) {
+           f_coeff = (*f_coeffs_)[0];
+           if (gmm::vect_size(*f_coeffs_) > 1) tau_adh = (*f_coeffs_)[1];
+           if (gmm::vect_size(*f_coeffs_) > 2) tresca_lim = (*f_coeffs_)[2];
+         }
+         else {
+           size_type ncoeffs = gmm::vect_size(*f_coeffs_)/pmf_coeff->nb_dof();
+           GMM_ASSERT1(ncoeffs >= 1 && ncoeffs <= 3, "Wrong vector dimension for friction coefficients");
+           gmm::resize(friction_coeff, pmf_coeff->nb_basic_dof());
+           pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(0,pmf_coeff->nb_dof(),ncoeffs)),
+                                    friction_coeff);
+           if (ncoeffs > 1) {
+             gmm::resize(tau_adhesion, pmf_coeff->nb_basic_dof());
+             pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(1,pmf_coeff->nb_dof(),ncoeffs)),
+                                      tau_adhesion);
+           }
+           if (ncoeffs > 2) {
+             gmm::resize(tresca_limit, pmf_coeff->nb_basic_dof());
+             pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(2,pmf_coeff->nb_dof(),ncoeffs)),
+                                      tresca_limit);
+           }
++>>>>>>> upstream
          }
  
          if (WT_ && gmm::vect_size(*WT_)) {
@@@ -441,7 -483,7 +630,11 @@@
      const mesh_fem &mf_u2;      // displacements of the mortar side projected on the non-mortar side
      const mesh_fem *pmf_lambda; // Lagrange multipliers defined on the non-mortar side
      const mesh_fem *pmf_coeff;  // coefficient of friction defined on the non-mortar side
++<<<<<<< HEAD
 +    base_vector U1, U2, lambda, friction_coeff, WT1, WT2;
++=======
+     base_vector U1, U2, lambda, friction_coeff, tau_adhesion, tresca_limit, WT1, WT2;
++>>>>>>> upstream
  
      template <typename VECT1>
      contact_nonmatching_meshes_nonlinear_term
@@@ -449,17 -491,18 +642,30 @@@
       const mesh_fem &mf_u1_, const VECT1 &U1_,
       const mesh_fem &mf_u2_, const VECT1 &U2_,
       const mesh_fem *pmf_lambda_ = 0, const VECT1 *lambda_ = 0,
++<<<<<<< HEAD
 +     const mesh_fem *pmf_coeff_ = 0, const VECT1 *f_coeff_ = 0,
++=======
+      const mesh_fem *pmf_coeff_ = 0, const VECT1 *f_coeffs_ = 0,
++>>>>>>> upstream
       scalar_type alpha_ = scalar_type(1),
       const VECT1 *WT1_ = 0, const VECT1 *WT2_ = 0
      )
        : contact_nonlinear_term(mf_u1_.linked_mesh().dim(), option_, r_,
++<<<<<<< HEAD
 +                               (f_coeff_ == 0), alpha_
++=======
+                                (f_coeffs_ == 0), alpha_
++>>>>>>> upstream
                                ),
          mf_u1(mf_u1_), mf_u2(mf_u2_),
          pmf_lambda(pmf_lambda_), pmf_coeff(pmf_coeff_),
          U1(mf_u1.nb_basic_dof()), U2(mf_u2.nb_basic_dof()),
++<<<<<<< HEAD
 +        lambda(0), friction_coeff(0), WT1(0), WT2(0)
++=======
+         lambda(0), friction_coeff(0), tau_adhesion(0), tresca_limit(0),
+         WT1(0), WT2(0)
++>>>>>>> upstream
      {
  
        GMM_ASSERT1(mf_u2.linked_mesh().dim() == N,
@@@ -469,16 -512,32 +675,44 @@@
        mf_u2.extend_vector(U2_, U2);
  
        if (pmf_lambda) {
++<<<<<<< HEAD
 +        lambda.resize(pmf_lambda->nb_basic_dof()); 
++=======
+         lambda.resize(pmf_lambda->nb_basic_dof());
++>>>>>>> upstream
          pmf_lambda->extend_vector(*lambda_, lambda);
        }
  
        if (!contact_only) {
++<<<<<<< HEAD
 +        if (!pmf_coeff)
 +          f_coeff = (*f_coeff_)[0];
 +        else {
 +          friction_coeff.resize(pmf_coeff->nb_basic_dof());
 +          pmf_coeff->extend_vector(*f_coeff_, friction_coeff);
++=======
+         if (!pmf_coeff) {
+           f_coeff = (*f_coeffs_)[0];
+           if (gmm::vect_size(*f_coeffs_) > 1) tau_adh = (*f_coeffs_)[1];
+           if (gmm::vect_size(*f_coeffs_) > 2) tresca_lim = (*f_coeffs_)[2];
+         }
+         else {
+           size_type ncoeffs = gmm::vect_size(*f_coeffs_)/pmf_coeff->nb_dof();
+           GMM_ASSERT1(ncoeffs >= 1 && ncoeffs <= 3, "Wrong vector dimension for friction coefficients");
+           gmm::resize(friction_coeff, pmf_coeff->nb_basic_dof());
+           pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(0,pmf_coeff->nb_dof(),ncoeffs)),
+                                    friction_coeff);
+           if (ncoeffs > 1) {
+             gmm::resize(tau_adhesion, pmf_coeff->nb_basic_dof());
+             pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(1,pmf_coeff->nb_dof(),ncoeffs)),
+                                      tau_adhesion);
+           }
+           if (ncoeffs > 2) {
+             gmm::resize(tresca_limit, pmf_coeff->nb_basic_dof());
+             pmf_coeff->extend_vector(gmm::sub_vector(*f_coeffs_, gmm::sub_slice(2,pmf_coeff->nb_dof(),ncoeffs)),
+                                      tresca_limit);
+           }
++>>>>>>> upstream
          }
          if (WT1_ && WT2_ && gmm::vect_size(*WT1_) && gmm::vect_size(*WT2_)) {
            WT1.resize(mf_u1.nb_basic_dof());
@@@ -566,16 -625,20 +800,32 @@@
    template<typename VEC>
    void asm_level_set_normal_source_term
    (VEC &R, const mesh_im &mim,
++<<<<<<< HEAD
 +   const getfem::mesh_fem &mf_u, // const VEC &U,
++=======
+    const getfem::mesh_fem &mf_u,
++>>>>>>> upstream
     const getfem::mesh_fem &mf_obs, const VEC &obs,
     const getfem::mesh_fem &mf_lambda, const VEC &lambda,
     const mesh_region &rg) {
  
++<<<<<<< HEAD
 +    VEC U;
 +    gmm::resize(U, mf_u.nb_dof());
 +    scalar_type r(0.);
 +    contact_rigid_obstacle_nonlinear_term
 +      nterm(RHS_U_V1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda);
++=======
+     bool contact_only = (mf_lambda.get_qdim() == 1);
+ 
+     VEC U;
+     gmm::resize(U, mf_u.nb_dof());
+     scalar_type dummy_r(0.);
+     VEC dummy_f_coeff; gmm::resize(dummy_f_coeff,1);
+     contact_rigid_obstacle_nonlinear_term
+       nterm(RHS_U_V1, dummy_r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
+             0, contact_only ? 0 : &dummy_f_coeff);
++>>>>>>> upstream
  
      getfem::generic_assembly assem;
      assem.set("V(#1)+=comp(NonLin$1(#1,#1,#2,#3).vBase(#1))(i,:,i); ");
@@@ -593,39 -656,85 +843,118 @@@
    (const mesh_im &mim,
     const getfem::mesh_fem &mf_u, const VEC &U,
     const getfem::mesh_fem &mf_obs, const VEC &obs,
++<<<<<<< HEAD
 +   const mesh_region &rg, scalar_type threshold_factor=0.0) {
 +
 +    //FIXME: use an adapted integration method
 +
 +    // assemble an estimator of the mesh size
 +    getfem::mesh_fem mf_mesh_size(mf_u.linked_mesh());
 +    mf_mesh_size.set_qdim(1);
 +    mf_mesh_size.set_classical_finite_element(1);
 +    VEC vec_mesh_size(mf_mesh_size.nb_dof());
 +
 +    getfem::generic_assembly assem_mesh_size;
 +    assem_mesh_size.set("V(#1)+=comp(Base(#1))");
 +    assem_mesh_size.push_mi(mim);
 +    assem_mesh_size.push_mf(mf_mesh_size);
 +    assem_mesh_size.push_vec(vec_mesh_size);
 +    assem_mesh_size.assembly(rg);
 +    if (mf_u.get_qdim() == 3)
 +      for (size_type i=0; i < gmm::vect_size(vec_mesh_size); i++)
 +        vec_mesh_size[i] = sqrt(vec_mesh_size[i]);
 +
 +    // compute the total contact area
 +    // remark: the CONTACT_FLAG option misuses r as threshold factor and mf_lambda
 +    //         as mesh size estimation
 +    scalar_type r(threshold_factor);
 +    contact_rigid_obstacle_nonlinear_term
 +      nterm(CONTACT_FLAG, r, mf_u, U, mf_obs, obs, &mf_mesh_size, &vec_mesh_size);
++=======
+    const mesh_region &rg, scalar_type threshold_factor=0.0,
+    const getfem::mesh_fem *mf_lambda=0, const VEC *lambda=0,
+    scalar_type threshold_pressure_factor=0.0) {
+ 
+     if (!rg.get_parent_mesh())
+       rg.from_mesh(mim.linked_mesh());
+     getfem::mesh_fem mf_ca(mf_u.linked_mesh());
+     mf_ca.set_classical_finite_element(rg.index(),1);
+ 
+     VEC mesh_size(mf_ca.nb_dof());
+     VEC mesh_size2(mf_ca.nb_dof());
+     { // assemble an estimator of the mesh size
+       getfem::generic_assembly assem_mesh_size;
+       assem_mesh_size.set("V(#1)+=comp(Base(#1))");
+       assem_mesh_size.push_mi(mim);
+       assem_mesh_size.push_mf(mf_ca);
+       assem_mesh_size.push_vec(mesh_size2);
+       assem_mesh_size.assembly(rg);
+       for (dal::bv_visitor_c dof(mf_ca.basic_dof_on_region(rg));
+            !dof.finished(); ++dof)
+         mesh_size[dof] = sqrt(mesh_size2[dof]);
+     }
+ 
+     VEC threshold(mf_ca.nb_dof());
+     if (mf_lambda && lambda) {
+       VEC pressure(mf_ca.nb_dof());
+       VEC dummy_f_coeff(1);
+       bool contact_only = (mf_lambda->get_qdim() == 1);
+       contact_rigid_obstacle_nonlinear_term
+         nterm_pressure(CONTACT_PRESSURE, 0., mf_u, U, mf_obs, obs,
+                        mf_lambda, lambda, 0, contact_only ? 0 : &dummy_f_coeff);
+ 
+       getfem::generic_assembly assem_pressure;
+       assem_pressure.set("V(#4)+=comp(NonLin(#1,#1,#2,#3).Base(#4))(i,:)");
+       assem_pressure.push_mi(mim);
+       assem_pressure.push_mf(mf_u);
+       assem_pressure.push_mf(mf_obs);
+       assem_pressure.push_mf(*mf_lambda);
+       assem_pressure.push_mf(mf_ca);
+       assem_pressure.push_nonlinear_term(&nterm_pressure);
+       assem_pressure.push_vec(pressure);
+       assem_pressure.assembly(rg);
+       for (dal::bv_visitor_c dof(mf_ca.basic_dof_on_region(rg));
+            !dof.finished(); ++dof)
+         pressure[dof] /= mesh_size2[dof];
+ 
+       // in areas where pressure is clearly non-zero set a low threshold
+       // in order to avoid false negative contact detection
+       scalar_type threshold_pressure(threshold_pressure_factor *
+                                      gmm::vect_norminf(pressure));
+       gmm::copy(gmm::scaled(mesh_size, scalar_type(-1)), threshold);
+       for (getfem::mr_visitor v(rg); !v.finished(); ++v) {
+         size_type nbdof = mf_ca.nb_basic_dof_of_face_of_element(v.cv(), v.f());
+         mesh_fem::ind_dof_face_ct::const_iterator
+           itdof = mf_ca.ind_basic_dof_of_face_of_element(v.cv(), v.f()).begin();
+         bool all_positive = true;
+         for (size_type k=0; k < nbdof; ++k, ++itdof)
+           if (pressure[*itdof] < threshold_pressure) { all_positive = false; break; }
+         if (!all_positive) {
+           itdof = mf_ca.ind_basic_dof_of_face_of_element(v.cv(), v.f()).begin();
+           for (size_type k=0; k < nbdof; ++k, ++itdof)
+             threshold[*itdof] = threshold_factor * mesh_size[*itdof];
+         }
+       }
+     }
+     else
+       gmm::copy(gmm::scaled(mesh_size, threshold_factor), threshold);
+ 
+     // compute the total contact area
+     // remark: the CONTACT_FLAG option misuses lambda as a threshold field
+     contact_rigid_obstacle_nonlinear_term
+       nterm(CONTACT_FLAG, 0., mf_u, U, mf_obs, obs, &mf_ca, &threshold);
++>>>>>>> upstream
  
      getfem::generic_assembly assem;
      assem.set("V()+=comp(NonLin(#1,#1,#2,#3))(i)");
      assem.push_mi(mim);
      assem.push_mf(mf_u);
      assem.push_mf(mf_obs);
++<<<<<<< HEAD
 +    assem.push_mf(mf_mesh_size);
++=======
+     assem.push_mf(mf_ca);
++>>>>>>> upstream
      assem.push_nonlinear_term(&nterm);
      std::vector<scalar_type> v(1);
      assem.push_vec(v);
@@@ -637,17 -746,21 +966,35 @@@
    template<typename VEC>
    void asm_nonmatching_meshes_normal_source_term
    (VEC &R, const mesh_im &mim,
++<<<<<<< HEAD
 +   const getfem::mesh_fem &mf_u1, // const VEC &U1,
 +   const getfem::mesh_fem &mf_u2_proj, // const VEC &U2_proj,
 +   const getfem::mesh_fem &mf_lambda, const VEC &lambda,
 +   const mesh_region &rg) {
 +
 +    VEC U1, U2_proj;
 +    gmm::resize(U1, mf_u1.nb_dof());
 +    gmm::resize(U2_proj, mf_u2_proj.nb_dof());
 +    scalar_type r(0);
 +    contact_nonmatching_meshes_nonlinear_term
 +      nterm(RHS_U_V1, r, mf_u1, U1, mf_u2_proj, U2_proj, &mf_lambda, &lambda);
++=======
+    const getfem::mesh_fem &mf_u1,
+    const getfem::mesh_fem &mf_u2_proj,
+    const getfem::mesh_fem &mf_lambda, const VEC &lambda,
+    const mesh_region &rg) {
+ 
+     bool contact_only = (mf_lambda.get_qdim() == 1);
+ 
+     VEC U1, U2_proj;
+     gmm::resize(U1, mf_u1.nb_dof());
+     gmm::resize(U2_proj, mf_u2_proj.nb_dof());
+     scalar_type dummy_r(0);
+     VEC dummy_f_coeff; gmm::resize(dummy_f_coeff,1);
+     contact_nonmatching_meshes_nonlinear_term
+       nterm(RHS_U_V1, dummy_r, mf_u1, U1, mf_u2_proj, U2_proj, &mf_lambda, &lambda,
+             0, contact_only ? 0 : &dummy_f_coeff);
++>>>>>>> upstream
  
      getfem::generic_assembly assem;
      assem.set("V(#1)+=comp(NonLin(#1,#1,#2,#3).vBase(#1))(i,:,i)");
@@@ -665,39 -778,86 +1012,119 @@@
    (const mesh_im &mim,
     const getfem::mesh_fem &mf_u1, const VEC &U1,
     const getfem::mesh_fem &mf_u2_proj, const VEC &U2_proj,
++<<<<<<< HEAD
 +   const mesh_region &rg, scalar_type threshold_factor=0.0) {
 +
 +    //FIXME: use an adapted integration method
 +
 +    // assemble an estimator of the mesh size
 +    getfem::mesh_fem mf_mesh_size(mf_u1.linked_mesh());
 +    mf_mesh_size.set_qdim(1);
 +    mf_mesh_size.set_classical_finite_element(1);
 +    VEC vec_mesh_size(mf_mesh_size.nb_dof());
 +
 +    getfem::generic_assembly assem_mesh_size;
 +    assem_mesh_size.set("V(#1)+=comp(Base(#1))");
 +    assem_mesh_size.push_mi(mim);
 +    assem_mesh_size.push_mf(mf_mesh_size);
 +    assem_mesh_size.push_vec(vec_mesh_size);
 +    assem_mesh_size.assembly(rg);
 +    if (mf_u1.get_qdim() == 3)
 +      for (size_type i=0; i < gmm::vect_size(vec_mesh_size); i++)
 +        vec_mesh_size[i] = sqrt(vec_mesh_size[i]);
 +    
 +    // compute the total contact area
 +    // remark: the CONTACT_FLAG option misuses r as threshold factor and mf_lambda
 +    //         as mesh size estimation
 +    scalar_type r(threshold_factor);
 +    contact_nonmatching_meshes_nonlinear_term
 +      nterm(CONTACT_FLAG, r, mf_u1, U1, mf_u2_proj, U2_proj, &mf_mesh_size, &vec_mesh_size);
++=======
+    const mesh_region &rg, scalar_type threshold_factor=0.0,
+    const getfem::mesh_fem *mf_lambda=0, const VEC *lambda=0,
+    scalar_type threshold_pressure_factor=0.0) {
+ 
+     if (!rg.get_parent_mesh())
+       rg.from_mesh(mim.linked_mesh());
+     getfem::mesh_fem mf_ca(mf_u1.linked_mesh());
+     mf_ca.set_classical_finite_element(rg.index(),1);
+ 
+     VEC mesh_size(mf_ca.nb_dof());
+     VEC mesh_size2(mf_ca.nb_dof());
+     { // assemble an estimator of the mesh size
+       getfem::generic_assembly assem_mesh_size;
+       assem_mesh_size.set("V(#1)+=comp(Base(#1))");
+       assem_mesh_size.push_mi(mim);
+       assem_mesh_size.push_mf(mf_ca);
+       assem_mesh_size.push_vec(mesh_size2);
+       assem_mesh_size.assembly(rg);
+       for (dal::bv_visitor_c dof(mf_ca.basic_dof_on_region(rg));
+            !dof.finished(); ++dof)
+         mesh_size[dof] = sqrt(mesh_size2[dof]);
+     }
+ 
+     VEC threshold(mf_ca.nb_dof());
+     if (mf_lambda && lambda) {
+       VEC pressure(mf_ca.nb_dof());
+       VEC dummy_f_coeff(1);
+       bool contact_only = (mf_lambda->get_qdim() == 1);
+       contact_nonmatching_meshes_nonlinear_term
+         nterm_pressure(CONTACT_PRESSURE, 0., mf_u1, U1, mf_u2_proj, U2_proj,
+                        mf_lambda, lambda, 0, contact_only ? 0 : &dummy_f_coeff);
+ 
+       getfem::generic_assembly assem_pressure;
+       assem_pressure.set("V(#4)+=comp(NonLin(#1,#1,#2,#3).Base(#4))(i,:)");
+       assem_pressure.push_mi(mim);
+       assem_pressure.push_mf(mf_u1);
+       assem_pressure.push_mf(mf_u2_proj);
+       assem_pressure.push_mf(*mf_lambda);
+       assem_pressure.push_mf(mf_ca);
+       assem_pressure.push_nonlinear_term(&nterm_pressure);
+       assem_pressure.push_vec(pressure);
+       assem_pressure.assembly(rg);
+       for (dal::bv_visitor_c dof(mf_ca.basic_dof_on_region(rg));
+            !dof.finished(); ++dof)
+         pressure[dof] /= mesh_size2[dof];
+ 
+       // in areas where pressure is clearly non-zero set a low threshold
+       // in order to avoid false negative contact detection
+       scalar_type threshold_pressure(threshold_pressure_factor *
+                                      gmm::vect_norminf(pressure));
+       gmm::copy(gmm::scaled(mesh_size, scalar_type(-1)), threshold);
+       for (getfem::mr_visitor v(rg); !v.finished(); ++v) {
+         size_type nbdof = mf_ca.nb_basic_dof_of_face_of_element(v.cv(), v.f());
+         mesh_fem::ind_dof_face_ct::const_iterator
+           itdof = mf_ca.ind_basic_dof_of_face_of_element(v.cv(), v.f()).begin();
+         bool all_positive = true;
+         for (size_type k=0; k < nbdof; ++k, ++itdof)
+           if (pressure[*itdof] < threshold_pressure) { all_positive = false; break; }
+         if (!all_positive) {
+           itdof = mf_ca.ind_basic_dof_of_face_of_element(v.cv(), v.f()).begin();
+           for (size_type k=0; k < nbdof; ++k, ++itdof)
+             threshold[*itdof] = threshold_factor * mesh_size[*itdof];
+         }
+       }
+     }
+     else
+       gmm::copy(gmm::scaled(mesh_size, threshold_factor), threshold);
+ 
+ 
+     // compute the total contact area
+     // remark: the CONTACT_FLAG option misuses lambda as a threshold field
+     contact_nonmatching_meshes_nonlinear_term
+       nterm(CONTACT_FLAG, 0., mf_u1, U1, mf_u2_proj, U2_proj, &mf_ca, &threshold);
++>>>>>>> upstream
  
      getfem::generic_assembly assem;
      assem.set("V()+=comp(NonLin(#1,#1,#2,#3))(i)");
      assem.push_mi(mim);
      assem.push_mf(mf_u1);
      assem.push_mf(mf_u2_proj);
++<<<<<<< HEAD
 +    assem.push_mf(mf_mesh_size);
++=======
+     assem.push_mf(mf_ca);
++>>>>>>> upstream
      assem.push_nonlinear_term(&nterm);
      std::vector<scalar_type> v(1);
      assem.push_vec(v);
@@@ -712,60 -872,102 +1139,159 @@@
  
  
  
++<<<<<<< HEAD
 +
 +  /** Add a large sliding contact with friction brick to the model.
 +      This brick is able to deal with auto-contact, contact between
 +      several deformable bodies and contact with rigid obstacles.
 +      The condition is applied on the variable `varname_u` on the
 +      boundary corresponding to `region`. `dataname_r` is the augmentation
 +      parameter of the augmented Lagrangian. `dataname_friction_coeff`
 +      is the friction coefficient. `mim` is an integration method on the
 +      boundary. `varname_u` is the variable on which the contact condition 
 +      will be prescribed (should be of displacement type). `multname` is 
 +      a multiplier defined on the boundary which will represent the contact
 +      force. If no additional boundary or rigid
 +      obstacle is added, only auto-contact will be detected. Use
 +      `add_boundary_to_large_sliding_contact_brick` and
 +      `add_rigid_obstacle_to_large_sliding_contact_brick` to add contact
 +      boundaries and rigid obstacles.
 +  */
 +  size_type add_integral_large_sliding_contact_brick
 +  (model &md, const mesh_im &mim, const std::string &varname_u,
 +   const std::string &multname, const std::string &dataname_r,
 +   const std::string &dataname_friction_coeff, size_type region);
 +
 +
 +  /** Add a contact boundary to an existing large sliding contact brick.
 +      `indbrick` is the brick index.
 +  */
 +  void add_boundary_to_large_sliding_contact_brick
 +  (model &md, size_type indbrick, const mesh_im &mim,
 +   const std::string &varname_u, const std::string &multname,
 +   size_type region);
 +
 +  /** Add a rigid obstacle to an existing large sliding contact brick.
 +      `indbrick` is the brick index, `obs` is the expression of a
 +      function which should be closed to a signed distance to the obstacle.
 +  */
 +  void add_rigid_obstacle_to_large_sliding_contact_brick
 +  (model &md, size_type indbrick, const std::string &obs);
 +
 +
 +
 +
 +
 +
 +
 +#ifdef EXPERIMENTAL_PURPOSE_ONLY
 +  // Experimental implementation of contact condition with Nitsche method.
 +  // To be deleted when a more general implementation will be designed.
 +  size_type add_Nitsche_contact_with_rigid_obstacle_brick
 +  (model &md, const mesh_im &mim, const std::string &varname_u,
 +   const std::string &dataname_obs, const std::string &dataname_r,
 +   const std::string &dataname_friction_coeff,
 +   const std::string &dataname_lambda, const std::string &dataname_mu,
 +   size_type region);
 +#endif
++=======
+   /** Adds a contact condition with or without Coulomb friction on the variable
+       `varname_u` and the mesh boundary `region`. The contact condition
+       is prescribed with Nitsche's method. The rigid obstacle should
+       be described with the data `dataname_obstacle` being a signed distance to
+       the obstacle (interpolated on a finite element method).
+       `gamma0name` is the Nitsche's method parameter.
+       `theta` is a scalar value which can be
+       positive or negative. `theta = 1` corresponds to the standard symmetric
+       method which is conditionnaly coercive for  `gamma0` small.
+       `theta = -1` corresponds to the skew-symmetric method which is
+       inconditionnaly coercive. `theta = 0` is the simplest method
+       for which the second derivative of the Neumann term is not necessary.
+       The optional parameter `dataname_friction_coeff` is the friction
+       coefficient which could be constant or defined on a finite element
+       method.
+       CAUTION: This brick has to be added in the model after all the bricks
+       corresponding to partial differential terms having a Neumann term.
+       Moreover, This brick can only be applied to bricks declaring their
+       Neumann terms. Returns the brick index in the model.
+   */
+   size_type add_Nitsche_contact_with_rigid_obstacle_brick
+   (model &md, const mesh_im &mim, const std::string &varname_u,
+    const std::string &dataname_obs, const std::string &dataname_gamma0,
+    scalar_type theta,
+    const std::string &dataname_friction_coeff,
+    const std::string &dataname_alpha,
+    const std::string &dataname_wt,
+    size_type region);
+ 
+ #ifdef EXPERIMENTAL_PURPOSE_ONLY
+ 
+   /** Adds a contact condition with or without Coulomb friction on the variable
+       `varname_u` and the mesh boundary `region`. The contact condition
+       is prescribed with Nitsche's method. The rigid obstacle should
+       be described with the data `dataname_obstacle` being a signed distance to
+       the obstacle (interpolated on a finite element method).
+       `gamma0name` is the Nitsche's method parameter.
+       `theta` is a scalar value which can be
+       positive or negative. `theta = 1` corresponds to the standard symmetric
+       method which is conditionnaly coercive for  `gamma0` small.
+       `theta = -1` corresponds to the skew-symmetric method which is
+       inconditionnaly coercive. `theta = 0` is the simplest method
+       for which the second derivative of the Neumann term is not necessary.
+       The optional parameter `dataname_friction_coeff` is the friction
+       coefficient which could be constant or defined on a finite element
+       method.
+       CAUTION: This brick has to be added in the model after all the bricks
+       corresponding to partial differential terms having a Neumann term.
+       Moreover, This brick can only be applied to bricks declaring their
+       Neumann terms. Returns the brick index in the model.
+   */
+   size_type add_Nitsche_midpoint_contact_with_rigid_obstacle_brick
+   (model &md, const mesh_im &mim, const std::string &varname_u,
+    const std::string &dataname_obs, const std::string &dataname_gamma0,
+    scalar_type theta,
+    const std::string &dataname_friction_coeff,
+    const std::string &dataname_alpha,
+    const std::string &dataname_wt,
+    size_type region, size_type option);
+ 
+ #endif
+ 
+ 
+ 
+   /** Adds a contact condition with or without Coulomb friction between
+  two bodies in a fictitious domain. The contact condition is applied on
+  the variable `varname_u1` corresponds with the first
+  and slave body with Nitsche's method and on the variable `varname_u2`
+  corresponds with the second and master body with Nitsche's method.
+  The contact condition is evaluated on the fictitious slave bondary.
+  The first body should be described by the level-set `dataname_d1`
+  and the second body should be described by the level-set
+ `dataname_d2`. `gamma0name` is the Nitsche's method parameter.
+  `theta` is a scalar value which can be positive or negative.
+  `theta = 1` corresponds to the standard symmetric method which
+  is conditionnaly coercive for  `gamma0` small.
+  `theta = -1` corresponds to the skew-symmetric method which is
+  inconditionnaly coercive. `theta = 0` is the simplest method for
+  which the second derivative of the Neumann term is not necessary. 
+ The optional parameter `dataname_friction_coeff` is the friction 
+ coefficient which could be constant or defined on a finite element method. 
+ CAUTION: This brick has to be added in the model
+  after all the bricks corresponding to partial differential
+  terms having a Neumann term. Moreover, This brick can only
+  be applied to bricks declaring their Neumann terms. Returns the brick index in the model. 
+ 
+   */
+   size_type add_Nitsche_fictitious_domain_contact_brick
+   (model &md, const mesh_im &mim, const std::string &varname_u1,
+    const std::string &varname_u2, const std::string &dataname_d1,
+    const std::string &dataname_d2, const std::string &dataname_gamma0,
+    scalar_type theta,
+    const std::string &dataname_friction_coeff,
+    const std::string &dataname_alpha,
+    const std::string &dataname_wt1, const std::string &dataname_wt2);
+ 
++>>>>>>> upstream
  
  }  /* end of namespace getfem.                                             */
  
diff --cc src/getfem/getfem_contact_and_friction_nodal.h
index 488c971,f27c754..78484e5
--- a/src/getfem/getfem_contact_and_friction_nodal.h
+++ b/src/getfem/getfem_contact_and_friction_nodal.h
@@@ -40,8 -40,6 +40,11 @@@
  
  #include "getfem_models.h"
  
++<<<<<<< HEAD
 +using std::endl; using std::cout; using std::cerr;
 +using std::ends; using std::cin;
++=======
++>>>>>>> upstream
  namespace getfem {
  
   typedef gmm::row_matrix<gmm::rsvector<scalar_type> > CONTACT_B_MATRIX;
@@@ -100,7 -98,8 +103,12 @@@
     CONTACT_B_MATRIX &BN, CONTACT_B_MATRIX &BT,
     std::string dataname_friction_coeff,
     std::string dataname_gap="", std::string dataname_alpha="",
++<<<<<<< HEAD
 +   int aug_version=1, bool Tresca_version=false, std::string dataname_threshold = "", bool Hughes_stabilized=false);
++=======
+    int aug_version=1, bool Tresca_version=false, const std::string dataname_threshold="",
+    std::string dataname_gamma="", std::string dataname_wt="", bool Hughes_stabilized=false);
++>>>>>>> upstream
  
    /** Can be used to change the matrix BN of a basic contact/friction brick
     */
@@@ -180,12 -179,12 +188,20 @@@
     CONTACT_B_MATRIX &BN, CONTACT_B_MATRIX &BT, CONTACT_B_MATRIX &DN,CONTACT_B_MATRIX &DT,
     std::string dataname_friction_coeff,
     std::string dataname_gap="", std::string dataname_alpha="",
++<<<<<<< HEAD
 +   int aug_version=1, bool Tresca_version=false, std::string dataname_threshold="") {
++=======
+    int aug_version=1, bool Tresca_version=false, const std::string dataname_threshold="") {
++>>>>>>> upstream
  
      size_type indbrick = add_basic_contact_brick
        (md, varname_u, multname_n, multname_t, dataname_r, BN, BT,
         dataname_friction_coeff, dataname_gap, dataname_alpha,
++<<<<<<< HEAD
 +       aug_version, Tresca_version, dataname_threshold, true);
++=======
+        aug_version, Tresca_version, dataname_threshold, "", "", true);
++>>>>>>> upstream
      gmm::resize(contact_brick_set_DN(md, indbrick),
                  gmm::mat_nrows(DN), gmm::mat_ncols(DN));
      gmm::copy(DN, contact_brick_set_DN(md, indbrick));
@@@ -421,25 -420,25 +437,44 @@@
    // DEPRECATED FUNCTION NAMES
  
    IS_DEPRECATED inline size_type add_basic_contact_with_friction_brick
++<<<<<<< HEAD
 + (model &md, const std::string &varname_u, const std::string &multname_n,
 +   const std::string &multname_t, const std::string &dataname_r,
 +   CONTACT_B_MATRIX &BN, CONTACT_B_MATRIX &BT,
 +   std::string dataname_friction_coeff,
 +   std::string dataname_gap="", std::string dataname_alpha="",
 +   int aug_version=1, bool Tresca_version=false, std::string dataname_threshold = "", bool Hughes_stabilized=false)
 +  { return add_basic_contact_brick
 +      (md, varname_u, multname_n, multname_t, dataname_r, BN, BT, dataname_friction_coeff,
 +       dataname_gap, dataname_alpha, aug_version, Tresca_version, dataname_threshold, Hughes_stabilized); }
++=======
+     (model &md, const std::string &varname_u, const std::string &multname_n,
+      const std::string &multname_t, const std::string &dataname_r,
+      CONTACT_B_MATRIX &BN, CONTACT_B_MATRIX &BT,
+      std::string dataname_friction_coeff,
+      std::string dataname_gap="", std::string dataname_alpha="",
+      int aug_version=1, bool Tresca_version=false, bool Hughes_stabilized=false)
+   { return add_basic_contact_brick
+       (md, varname_u, multname_n, multname_t, dataname_r, BN, BT, dataname_friction_coeff,
+        dataname_gap, dataname_alpha, aug_version, Tresca_version, "", "", "", Hughes_stabilized); }
++>>>>>>> upstream
  
    IS_DEPRECATED inline size_type add_Hughes_stab_with_friction_contact_brick
      (model &md, const std::string &varname_u, const std::string &multname_n,
       const std::string &multname_t, const std::string &dataname_r,
       CONTACT_B_MATRIX &BN, CONTACT_B_MATRIX &BT, CONTACT_B_MATRIX &DN,CONTACT_B_MATRIX &DT,
       std::string dataname_friction_coeff, std::string dataname_gap="",
++<<<<<<< HEAD
 +     std::string dataname_alpha="", int aug_version=1, bool Tresca_version=false, std::string dataname_threshold="")
 +  { return add_Hughes_stab_basic_contact_brick
 +      (md, varname_u, multname_n, multname_t, dataname_r, BN, BT, DN, DT,
 +       dataname_friction_coeff, dataname_gap, dataname_alpha, aug_version, Tresca_version, dataname_threshold); }
++=======
+      std::string dataname_alpha="", int aug_version=1, bool Tresca_version=false)
+   { return add_Hughes_stab_basic_contact_brick
+       (md, varname_u, multname_n, multname_t, dataname_r, BN, BT, DN, DT,
+        dataname_friction_coeff, dataname_gap, dataname_alpha, aug_version, Tresca_version, ""); }
++>>>>>>> upstream
  
    // rigid obstacle
    IS_DEPRECATED inline size_type add_contact_with_rigid_obstacle_brick
diff --cc src/getfem/getfem_continuation.h
index 99c18e2,5f1de38..3f07ef2
--- a/src/getfem/getfem_continuation.h
+++ b/src/getfem/getfem_continuation.h
@@@ -34,10 -34,6 +34,13 @@@
      @author Yves Renard <Yves.Renard at insa-lyon.fr>
      @date October 17, 2011.
      @brief (approximate) Moore-Penrose (also called Gauss-Newton) continuation method.
++<<<<<<< HEAD
 +
 +    NOTE: The bordered systems involved are solved by a block eliminiation
 +    although the bordered matrix may be ill-conditioned in some cases!
 +    Nevertheless, the algorithm seems to work well.
++=======
++>>>>>>> upstream
  */
  #ifndef GETFEM_CONTINUATION_H__
  #define GETFEM_CONTINUATION_H__
@@@ -51,55 -47,119 +54,171 @@@ namespace getfem 
    // Abstract Moore-Penrose continuation method
    //=========================================================================
  
++<<<<<<< HEAD
 +
 +  const double tau_init = 1.e4;
 +  enum build_data { BUILD_F = 1, BUILD_F_x = 2, BUILD_ALL = 3 };
 +
 +  template <typename CONT_S, typename VECT> 
 +  double norm_(CONT_S &S, const VECT &x)
 +  { return sqrt(S.sp(x, x)); }
 +  
 +  template <typename CONT_S, typename VECT> 
 +  double w_sp_(CONT_S &S, const VECT &x1, const VECT &x2)
 +  { return S.scfac() * S.sp(x1, x2); }
 +
 +  template <typename CONT_S, typename VECT> 
 +  double sp_(CONT_S &S, const VECT &x1, const VECT &x2,
 +	     double gamma1, double gamma2)
 +  { return w_sp_(S, x1, x2) + gamma1 * gamma2; }
 +
 +  template <typename CONT_S, typename VECT> 
 +  double norm_(CONT_S &S, const VECT &x, double gamma)
 +  { return sqrt(sp_(S, x, x, gamma, gamma)); }
 +
 +
 +  template <typename CONT_S, typename VECT>
 +  void compute_tangent(CONT_S &S, const VECT &x, double gamma,
 +		       VECT &t_x, double &t_gamma) {
 +    VECT g(x), y(x);
 +    S.F_gamma(x, gamma, g);
 +    S.solve_grad(x, gamma, y, g);
 +    t_gamma = 1. / (t_gamma - w_sp_(S, t_x, y));
 +    S.scale(y, -t_gamma); S.copy(y, t_x);
 +    
 +    double no = norm_(S, t_x, t_gamma);
 +    S.scale(t_x, 1./no); t_gamma /= no;
 +
 +//     if (S.noisy() > 1) {
 +//       S.mult_grad(x, gamma, t_x, y); S.scaled_add(y, g, t_gamma, y);
 +//       cout << "new tangent computed with the residual " 
 +// 	   << norm_(S, y) << endl;
 +//     }
 +  }
 +
 +
 +  template <typename CONT_S, typename MAT, typename VECT>
 +  double test_function(CONT_S &S, const MAT &A, const VECT &g,
 +		       const VECT &t_x, double t_gamma) {
 +    double q, r, v_gamma, tau;
 +    VECT v_x(g), y(g), z(g);
 +
 +    if (S.noisy() > 1) cout << "starting computing test function" << endl;
++=======
+   const double tau_init = 1.e6;
+   enum build_data { BUILD_F = 1, BUILD_F_x = 2, BUILD_ALL = 3 };
+ 
+   /* Compute a unit tangent at (x, gamma) that is accute to the incoming
+      tangent. */
+   template <typename CONT_S, typename VECT>
+   void compute_tangent(CONT_S &S, const VECT &x, double gamma,
+ 		       VECT &t_x, double &t_gamma) {
+     double r;
+     VECT g(x), y(x);
+     S.F_gamma(x, gamma, g);
+     S.solve_grad(x, gamma, y, g);
+     t_gamma = 1. / (t_gamma - S.w_sp(t_x, y));
+     S.scale(y, -t_gamma); S.copy(y, t_x);
+     
+     double no = S.w_norm(t_x, t_gamma);
+     S.scale(t_x, 1./no); t_gamma /= no;
+ 
+     S.mult_grad(x, gamma, t_x, y); S.scaled_add(y, g, t_gamma, y);
+     r = S.norm(y);
+     if (r > 1.e-10)
+       GMM_WARNING1("Tangent computed with the residual " << r);
+   }
+ 
+   /* Calculate a tangent vector at (x, gamma) + h * (T_x, T_gamma) and test
+      whether it is close to (T_x, T_gamma). Informatively, compare it with
+      (t_x, t_gamma), as well. */
+   template <typename CONT_S, typename VECT>
+   bool test_tangent(CONT_S &S, const VECT &x, double gamma,
+ 		    const VECT &T_x, double T_gamma,
+ 		    const VECT &t_x, double t_gamma, double h) {
+     bool res = false;
+     double Gamma, T_Gamma = T_gamma, cang;
+     VECT X(x), T_X(T_x);
+     
+     S.scaled_add(x, T_x, h, X); Gamma = gamma + h * T_gamma;
+     S.set_build(BUILD_ALL);
+     compute_tangent(S, X, Gamma, T_X, T_Gamma);
+     
+     cang = S.cosang(T_X, T_x, T_Gamma, T_gamma);
+     if (S.noisy() > 1)
+       cout << "cos of the angle with the tested tangent " << cang << endl;
+     if (cang >= S.mincos()) res = true;
+     else {    
+       cang = S.cosang(T_X, t_x, T_Gamma, t_gamma);
+       if (S.noisy() > 1)
+ 	cout << "cos of the angle with the initial tangent " << cang << endl;
+     }
+     return res;
+   }
+ 
+   /* Simple tangent switch. */
+   template <typename CONT_S, typename VECT>
+   bool switch_tangent(CONT_S &S, const VECT &x, double gamma,
+ 		      VECT &t_x, double &t_gamma, double &h) {    
+     bool accepted;
+     double t_gamma0 = t_gamma, T_gamma = t_gamma, Gamma;
+     VECT t_x0(t_x), T_x(t_x), X(x);
+ 
+     if (S.noisy() > 0) cout  << "trying simple tangent switch" << endl;
+ 
+     if (S.noisy() > 0) cout << "starting computing a new tangent" << endl;
+     S.scaled_add(x, T_x, h, X); Gamma = gamma + h * T_gamma;
+     S.set_build(BUILD_ALL);
+     compute_tangent(S, X, Gamma, T_x, T_gamma);
+     
+     if (S.noisy() > 0)
+       cout << "starting testing the computed tangent" << endl;
+     double h_test = (-0.9) * S.h_min();
+     do {
+       h_test = -h_test
+ 	+ pow(10., floor(log10(- h_test / S.h_min()))) * S.h_min();
+       accepted = test_tangent(S, x, gamma, T_x, T_gamma,
+ 			      t_x, t_gamma, h_test);
+       if (!accepted) {
+ 	h_test *= -1.;
+ 	accepted = test_tangent(S, x, gamma, T_x, T_gamma,
+ 				t_x, t_gamma, h_test);
+       }
+     } while (!accepted && (h_test > -S.h_max()));
+     
+     if (accepted) {
+       S.copy(T_x, t_x); t_gamma = T_gamma;
+       if (h_test < 0) { 
+ 	S.scale(t_x, -1.); t_gamma *= -1.; h_test *= -1.;
+       }
+       if (S.noisy() > 0)
+ 	cout << "tangent direction switched, "
+ 	     << "starting computing a suitable step size" << endl;
+       bool h_adapted = false; h = S.h_init();
+       while (!h_adapted && (h > h_test)) {
+ 	h_adapted = test_tangent(S, x, gamma, t_x, t_gamma,
+ 				 t_x0, t_gamma0, h);
+ 	h *= S.h_dec();
+       }
+       h = (h_adapted) ? h / S.h_dec() : h_test;
+     } else
+       if (S.noisy() > 0) cout << "simple tangent switch has failed" << endl;
+     
+     return accepted;
+   }
+ 
+ 
+   /* Test function for bifurcation points for a given matrix. The first part
+      of the solution of the augmented system is passed in
+      (v_x, v_gamma). */
+   template <typename CONT_S, typename MAT, typename VECT>
+   double test_function(CONT_S &S, const MAT &A, const VECT &g,
+ 		       const VECT &t_x, double t_gamma,
+ 		       VECT &v_x, double &v_gamma) {
+     double q, r, tau;
+     VECT y(g), z(g);
+ 
++>>>>>>> upstream
      S.solve(A, y, z, g, S.b_x());
      v_gamma = (S.b_gamma() - S.sp(t_x, z)) / (t_gamma - S.sp(t_x, y));
      S.scaled_add(z, y, -v_gamma, v_x);
@@@ -113,93 -173,354 +232,435 @@@
      q = S.sp(t_x, v_x) + t_gamma * v_gamma + S.b_gamma() * tau; r += q * q;
      q = S.sp(S.c_x(), v_x) + S.c_gamma() * v_gamma + S.d() * tau - 1.;
      r += q * q; r = sqrt(r);
++<<<<<<< HEAD
 +    if (r > 1e-10)
++=======
+     if (r > 1.e-10)
++>>>>>>> upstream
        GMM_WARNING1("Test function evaluated with the residual " << r);
  
      return tau;
    }
  
++<<<<<<< HEAD
 +  template <typename CONT_S, typename VECT>
 +  double test_function(CONT_S &S, const VECT &x, double gamma,
 +		       const VECT &t_x, double t_gamma) {
 +    VECT g(x); S.F_gamma(x, gamma, g);
 +    typename CONT_S::MAT A; S.F_x(x, gamma, A);
 +    return test_function(S, A, g, t_x, t_gamma);
 +  }
 +
 +  template <typename CONT_S, typename VECT>
 +  bool test_smooth_bifurcation(CONT_S &S, const VECT &x, double gamma,
 +			       const VECT &t_x, double t_gamma) {
 +    double tau0 = S.tau1(), tau1 = S.tau2(),
 +      tau2 = test_function(S, x, gamma, t_x, t_gamma);
 +    S.set_tau1(tau1); S.set_tau2(tau2);
 +    return (tau2 * tau1 < 0) & (S.abs(tau1) < S.abs(tau0));
 +  }
 +
++=======
+   template <typename CONT_S, typename MAT, typename VECT>
+   double test_function(CONT_S &S, const MAT &A, const VECT &g,
+ 		       const VECT &t_x, double t_gamma) {
+     VECT v_x(g); double v_gamma;
+     return test_function(S, A, g, t_x, t_gamma, v_x, v_gamma);
+   }
+ 
+   /* Test function for bifurcation points for the gradient computed at
+      (x, gamma). */
+   template <typename CONT_S, typename VECT>
+   double test_function(CONT_S &S, const VECT &x, double gamma,
+ 		       const VECT &t_x, double t_gamma,
+ 		       VECT &v_x, double &v_gamma) {
+     typename CONT_S::MAT A; S.F_x(x, gamma, A);
+     VECT g(x); S.F_gamma(x, gamma, g);
+     return test_function(S, A, g, t_x, t_gamma, v_x, v_gamma);
+   }
+ 
+   template <typename CONT_S, typename VECT>
+   double test_function(CONT_S &S, const VECT &x, double gamma,
+ 		       const VECT &t_x, double t_gamma) {
+     VECT v_x(x); double v_gamma;
+     return test_function(S, x, gamma, t_x, t_gamma, v_x, v_gamma);
+   }
+ 
+   /* Test for smooth bifurcation points. */
+   template <typename CONT_S, typename VECT>
+   bool test_smooth_bifurcation(CONT_S &S, const VECT &x, double gamma,
+ 			       const VECT &t_x, double t_gamma) {
+     double tau0 = S.get_tau1(), tau1 = S.get_tau2(),
+       tau2 = test_function(S, x, gamma, t_x, t_gamma);
+     S.set_tau1(tau1); S.set_tau2(tau2);
+     return (tau2 * tau1 < 0) && (S.abs(tau1) < S.abs(tau0));
+   }
+ 
+   /* Test for non-smooth bifurcation points. */
++>>>>>>> upstream
    template <typename CONT_S, typename VECT>
    bool test_nonsmooth_bifurcation (CONT_S &S, const VECT &x1, double gamma1,
  				   const VECT &t_x1, double t_gamma1,
  				   const VECT &x2, double gamma2,
  				   const VECT &t_x2, double t_gamma2) {
      unsigned long nb_changes = 0;
++<<<<<<< HEAD
 +    double alpha = 0, delta = 1. / S.nb_test(), t_gamma,
 +      tau0, tau1 = tau_init, tau2 = S.tau2();
 +    VECT g1(x1), g2(x1), g(x1), t_x(x1);
 +    typename CONT_S::MAT A1, A2, A;
 +    S.F_gamma(x2, gamma2, g2);
 +    S.F_x(x1, gamma1, A1); S.F_gamma(x1, gamma1, g1);
 +    S.F_x(x2, gamma2, A2); S.F_x(x2, gamma2, A);
 +    S.init_tau_hist();
 +
 +    for(size_type i = 1; i < S.nb_test() + 1; ++i) {
 +      alpha += delta;
++=======
+     double alpha = 0., delta = S.delta_min(),
+       tau0 = tau_init, tau1= S.get_tau2(),tau2, tau_var_ref, t_gamma;
+     VECT g1(x1), g2(x1), g(x1), t_x(x1);
+ 
+     // compute gradients at the two given points
+     typename CONT_S::MAT A1, A2, A;
+     S.F_x(x2, gamma2, A2); S.F_x(x2, gamma2, A); S.F_gamma(x2, gamma2, g2);
+     S.F_x(x1, gamma1, A1); S.F_gamma(x1, gamma1, g1);
+     S.init_tau_graph();
+     tau2 = test_function(S, A2, g2, t_x2, t_gamma2);
+     tau_var_ref = std::max(S.abs(tau2 - tau1),
+ 			   (S.abs(tau1) + S.abs(tau2)) / 200);
+ 
+     // monitor sign changes of the test function on the convex combination
+     do {
+       alpha = std::min(alpha + delta, 1.);
++>>>>>>> upstream
        S.scaled_add(A1, 1. - alpha, A2, alpha, A);
        S.scaled_add(g1, 1. - alpha, g2, alpha, g);
        S.scaled_add(t_x1, 1. - alpha, t_x2, alpha, t_x);
        t_gamma = (1. - alpha) * t_gamma1 + alpha * t_gamma2;
        
++<<<<<<< HEAD
 +      tau0 = tau1; tau1 = tau2; tau2 = test_function(S, A, g, t_x, t_gamma);
 +      if ((tau2 * tau1 < 0) & (S.abs(tau1) < S.abs(tau0))) ++nb_changes;
 +      S.set_tau_hist(i, tau2);
 +    }
++=======
+       tau2 = test_function(S, A, g, t_x, t_gamma);
+       if ((tau2 * tau1 < 0) && (S.abs(tau1) < S.abs(tau0))) ++nb_changes;
+       S.insert_tau_graph(alpha, tau2);
+ 
+       if (S.abs(tau2 - tau1) < 0.5 * S.thrvar() * tau_var_ref)
+ 	delta = std::min(2 * delta, S.delta_max());
+       else if (S.abs(tau2 - tau1) > S.thrvar() * tau_var_ref) 
+ 	delta = std::max(0.1 * delta, S.delta_min());
+       tau0 = tau1; tau1 = tau2; 
+     } while (alpha < 1.);
++>>>>>>> upstream
      
      S.set_tau1(tau_init); S.set_tau2(tau2);
      return nb_changes % 2;
    }
    
++<<<<<<< HEAD
 +
 +  template <typename CONT_S, typename VECT>
 +  int test_direction(CONT_S &S, const VECT &x, double gamma,
 +		     const VECT &t_x, double t_gamma,
 +		     VECT &T_x, double &T_gamma, double h) {
 +    int res = 1;
 +    double Gamma, T_Gamma = T_gamma, ang;
 +    VECT X(x), T_X(T_x);
 +    
 +    S.scaled_add(x, T_x, h, X); Gamma = gamma + h * T_gamma;
 +    S.set_build(BUILD_ALL);
 +    compute_tangent(S, X, Gamma, T_X, T_Gamma);
 +    
 +    ang = sp_(S, T_x, T_X, T_gamma, T_Gamma);
 +    if (S.noisy() > 1)
 +      cout << "the angle with the tested tangent " << ang << endl;
 +    if (ang >=  0.996) res = (h > 0) ? 3 : 4;
 +    else {
 +      ang = sp_(S, t_x, T_X, t_gamma, T_Gamma);
 +      if (S.noisy() > 1)
 +	cout << "the angle with the starting tangent " << ang << endl;
 +      if (ang < 0.86 && ang > -0.86) {
 +	res = 2;
 +	S.copy(T_X, T_x); T_gamma = T_Gamma; // try the new tangent next(?)
 +      }
 +    }
 +    return res;
 +  }
 +
 +  template <typename CONT_S, typename VECT>
 +  void init_test_function(CONT_S &S, const VECT &x, double gamma,
 +			  const VECT &t_x, double t_gamma) {
 +    S.init_border(x);
++=======
+   /* Newton-type corrections for the couple ((X, Gamma), (T_x, T_gamma)).
+      The current direction of (T_x, T_gamma) is informatively compared with
+      (t_x, t_gamma). */
+   template <typename CONT_S, typename VECT>
+   bool newton_corr(CONT_S &S, VECT &X, double &Gamma, VECT &T_x,
+ 		   double &T_gamma, const VECT &t_x, double t_gamma,
+ 		   unsigned long &it) {
+     bool converged = false;
+     double Delta_Gamma, no, res, diff;
+     VECT F(X), g(X), Delta_X(X), y(X);
+ 
+     if (S.noisy() > 0) cout << "starting correction " << endl;
+     it = 0;
+     S.F(X, Gamma, F);
+     
+     do {
+       S.F_gamma(X, Gamma, g);
+       S.solve_grad(X, Gamma, Delta_X, y, F, g);
+       
+       Delta_Gamma = S.sp(T_x, Delta_X) / (S.sp(T_x, y) - T_gamma);
+       S.scaled_add(Delta_X, y, -Delta_Gamma, Delta_X);
+       S.scaled_add(X, Delta_X, -1., X); Gamma -= Delta_Gamma;
+       S.set_build(BUILD_ALL);
+       
+       T_gamma = 1. / (T_gamma - S.w_sp(T_x, y));
+       S.scale(y, -T_gamma); S.copy(y, T_x);
+       no = S.w_norm(T_x, T_gamma);
+       S.scale(T_x, 1./no); T_gamma /= no;
+ 
+       S.F(X, Gamma, F); res = S.norm(F); 
+       diff = S.w_norm(Delta_X, Delta_Gamma);
+       if (S.noisy() > 1)
+ 	cout << " iter " << it << " residual " << res
+ 	     << " difference " << diff 
+ 	     << " cosang " << S.cosang(T_x, t_x, T_gamma, t_gamma) << endl;
+ 
+       if (res <= S.maxres() && diff <= S.maxdiff()) {
+ 	converged = true;
+ 	// recalculate the final tangent, for sure
+ 	compute_tangent(S, X, Gamma, T_x, T_gamma);
+ 	break;
+       }
+ 
+       it++;      
+     } while (it < S.maxit() && res < 1.e8);
+     return converged;
+   }
+   
+   template <typename CONT_S, typename VECT>
+   bool newton_corr(CONT_S &S, VECT &X, double &Gamma, VECT &T_x,
+ 		   double &T_gamma, const VECT &t_x, double t_gamma) {
+     unsigned long it;
+     return newton_corr(S, X, Gamma, T_x, T_gamma, t_x, t_gamma, it);
+   }
+ 
+   /* Try to perform one predictor-corrector step starting from the couple
+      ((x, gamma), (t_x, t_gamma)). Return the resulting couple in the case of
+      convergence. */
+   template <typename CONT_S, typename VECT>
+   bool test_predict_dir(CONT_S &S, VECT &x, double &gamma,
+ 			VECT &t_x, double &t_gamma) {
+     bool converged = false;
+     double h =  S.h_init(), Gamma, T_gamma;
+     VECT X(x), T_x(x);
+     do { //step control
+       
+       // prediction
+       if (S.noisy() > 0) cout << "prediction with h = " << h << endl;
+       S.scaled_add(x, t_x, h, X); Gamma = gamma + h * t_gamma;
+       S.set_build(BUILD_ALL);
+       S.copy(t_x, T_x); T_gamma = t_gamma;
+ 
+       //correction
+       converged = newton_corr(S, X, Gamma, T_x, T_gamma, t_x, t_gamma);
+       
+       if (converged) {
+ 	// check the direction of the tangent found
+ 	S.scaled_add(X, x, -1., t_x); t_gamma = Gamma - gamma;
+ 	if (S.sp(T_x, t_x, T_gamma, t_gamma) < 0)
+ 	  { S.scale(T_x, -1.); T_gamma *= -1.; }
+ 	S.copy(X, x); gamma = Gamma;
+ 	S.copy(T_x, t_x); t_gamma = T_gamma;
+       }
+       else if (h > S.h_min())
+ 	  h = (0.199 * S.h_dec() * h > S.h_min()) ?
+ 	    0.199 * S.h_dec() * h : S.h_min();
+       else break;
+ 
+     } while(!converged);
+     return converged;
+   }
+ 
+   /* A tool for approximating a smooth bifurcation point close to (x, gamma)
+      and locating the two branches emanating from there. */
+   template <typename CONT_S, typename VECT>
+   void treat_smooth_bif_point(CONT_S &S, const VECT &x, double gamma,
+ 			      const VECT &t_x, double t_gamma, double h) {
+     unsigned long i = 0;
+     double tau0 = S.get_tau1(), tau1 = S.get_tau2(),
+       gamma0 = gamma, Gamma, t_gamma0 = t_gamma, T_gamma = t_gamma, v_gamma;
+     VECT x0(x), X(x), t_x0(t_x), T_x(t_x), v_x(t_x);
+     
+     if (S.noisy() > 0)
+       cout  << "starting locating the bifurcation point" << endl;
+ 
+     // predictor-corrector steps with a secant-type step-length adaptation
+     h *= tau1 / (tau0 - tau1);
+     while ((S.abs(h) >= S.h_min()) && i < 10) {
+       if (S.noisy() > 0) cout << "prediction with h = " << h << endl;
+       S.scaled_add(x0, t_x0, h, X); Gamma = gamma0 + h * t_gamma0;
+       S.set_build(BUILD_ALL);
+       if (newton_corr(S, X, Gamma, T_x, T_gamma, t_x0, t_gamma0)) {
+ 	S.copy(X, x0); gamma0 = Gamma;
+ 	if (S.cosang(T_x, t_x0, T_gamma, t_gamma0) >= S.mincos())
+ 	  { S.copy(T_x, t_x0); t_gamma0 = T_gamma; }
+ 	tau0 = tau1;
+ 	tau1 = test_function(S, X, Gamma, t_x0, t_gamma0, v_x, v_gamma);
+ 	h *= tau1 / (tau0 - tau1);
+       }	else {
+ 	S.scaled_add(x0, t_x0, h, x0); gamma0 += h * t_gamma0;
+ 	test_function(S, x0, gamma0, t_x0, t_gamma0, v_x, v_gamma);
+ 	break;
+       }
+       ++i;
+     }
+     S.set_sing_point(x0, gamma0);
+     S.insert_tangent_sing(t_x0, t_gamma0);
+ 
+     if (S.noisy() > 0)
+       cout  << "starting searching for the second branch" << endl;
+     double no = S.w_norm(v_x, v_gamma);
+     S.scale(v_x, 1./no); v_gamma /= no;
+     if (test_predict_dir(S, x0, gamma0, v_x, v_gamma)
+ 	&& S.insert_tangent_sing(v_x, v_gamma))
+       { if (S.noisy() > 0) cout << "second branch found" << endl; }
+     else if (S.noisy() > 0) cout << "Second branch not found!" << endl;
+   }
+   
+   /* A tool for approximating a non-smooth point close to (x, gamma) and
+      locating (preferably) all smooth one-sided solution branches emanating
+      from there. It is supposed that (x, gamma) is up to the distance of
+      S.h_min() a last point of some smooth solution branch and (t_x, t_gamma)
+      is the corresponding tangent that directs to the end of this branch. */
+   template <typename CONT_S, typename VECT>
+   void treat_nonsmooth_point(CONT_S &S, const VECT &x, double gamma,
+ 			     const VECT &t_x, double t_gamma, int version) {
+     double gamma_end = gamma, Gamma, t_gamma0 = t_gamma, T_gamma = t_gamma,
+       h = S.h_min(), cang, mcos = S.mincos();
+     VECT x_end(x), X(x), t_x0(t_x), T_x(t_x);
+ 
+     // approximate the non-smooth point by a bisection-like algorithm
+     if (S.noisy() > 0)
+       cout  << "starting locating a non-smooth point" << endl;
+     S.scaled_add(x, t_x, h, X); Gamma = gamma + h * t_gamma;
+     S.set_build(BUILD_ALL);
+     if (newton_corr(S, X, Gamma, T_x, T_gamma, t_x0, t_gamma0)) {
+       cang = S.cosang(T_x, t_x0, T_gamma, t_gamma0);
+       if (cang >= mcos) mcos = (cang + 1.) / 2.;
+     }
+ 
+     S.copy(t_x0, T_x); T_gamma = t_gamma0;
+     h /= 2.;
+     for (unsigned long i = 0; i < 15; i++) {
+       if (S.noisy() > 0) cout << "prediction with h = " << h << endl;
+       S.scaled_add(x_end, t_x0, h, X); Gamma = gamma_end + h * t_gamma0;
+       S.set_build(BUILD_ALL);
+       if (newton_corr(S, X, Gamma, T_x, T_gamma, t_x0, t_gamma0)
+ 	  && (S.cosang(T_x, t_x, T_gamma, t_gamma) >= mcos)) {
+ 	S.copy(X, x_end); gamma_end = Gamma;
+ 	S.copy(T_x, t_x0); t_gamma0 = T_gamma;
+       } else {
+ 	S.copy(t_x0, T_x); T_gamma = t_gamma0;
+       }
+       h /= 2.;
+     }
+     S.scaled_add(x_end, t_x0, h, x_end); gamma_end += h * t_gamma0;
+     S.set_sing_point(x_end, gamma_end);
+ 
+     // take two different vectors to span a subspace of perturbations
+     if (S.noisy() > 0)
+       cout  << "starting a thorough search for other branches" << endl;
+     double t_gamma1 = t_gamma0, t_gamma2 = t_gamma0;
+     VECT t_x1(t_x0), t_x2(t_x0);
+     S.scale(t_x1, -1.); t_gamma1 *= -1.;
+     S.insert_tangent_sing(t_x1, t_gamma1);
+ 
+     h = S.h_min();
+     S.scaled_add(x_end, t_x0, h, X); Gamma = gamma_end + h * t_gamma0;
+     S.set_build(BUILD_ALL);
+     compute_tangent(S, X, Gamma, t_x2, t_gamma2);
+ 
+     // perturb the non-smooth point systematically to find new tangent
+     // predictions
+     bool index_changed;
+     unsigned long i1 = 0, i2 = 0, ncomb = 0;
+     double a, a1, a2, no;
+     S.clear(t_x0); t_gamma0 = 0.;
+ 
+     do {
+       for (unsigned long i = 0; i < S.nbdir(); i++) {
+ 	a = (2 * M_PI * double(i)) / double(S.nbdir());
+ 	a1 = h * sin(a); a2 = h * cos(a);
+ 	S.scaled_add(x_end, t_x1, a1, X); Gamma = gamma_end + a1 * t_gamma1;
+ 	S.scaled_add(X, t_x2, a2, X); Gamma += a2 * t_gamma2;
+ 	S.set_build(BUILD_ALL);
+ 	compute_tangent(S, X, Gamma, T_x, T_gamma);
+ 
+ 	if (S.abs(S.cosang(T_x, t_x0, T_gamma, t_gamma0)) < S.mincos()) {
+ 	  S.copy(T_x, t_x0); t_gamma0 = T_gamma;
+ 	  if (S.insert_tangent_predict(T_x, T_gamma)) {
+ 	    if (S.noisy() > 0)
+ 	      cout << "new potential tangent vector found, "
+ 		   << "trying one predictor-corrector step" << endl;
+ 	    S.copy(x_end, X); Gamma = gamma_end;
+ 	    
+ 	    if (test_predict_dir(S, X, Gamma, T_x, T_gamma)) {
+ 	      if (S.insert_tangent_sing(T_x, T_gamma)) {
+ 		if ((a == 0) && (ncomb == 0)
+ 		    && (S.abs(S.cosang(T_x, t_x0, T_gamma, t_gamma0))
+ 			>= S.mincos())) { i2 = 1; ncomb = 1; }
+ 		if (version) S.set_next_point(X, Gamma);
+ 	      }
+ 	      S.copy(x_end, X); Gamma = gamma_end;
+ 	      S.copy(t_x0, T_x); T_gamma = t_gamma0;
+ 	    }
+ 	    
+ 	    S.scale(T_x, -1.); T_gamma *= -1.;
+ 	    if (test_predict_dir(S, X, Gamma, T_x, T_gamma)
+ 		&& S.insert_tangent_sing(T_x, T_gamma) && version)
+ 	      S.set_next_point(X, Gamma);
+ 	  }
+ 	}
+       }
+       
+       // heuristics for varying the spanning vectors
+       if (i1 + 1 < i2) { ++i1; index_changed = true; }
+       else if(i2 + 1 < S.nb_tangent_sing())
+ 	{ ++i2; i1 = 0; index_changed = true; }
+       else index_changed = false;
+       if (index_changed) {
+ 	S.copy(S.get_t_x_sing(i1), t_x1); t_gamma1 = S.get_t_gamma_sing(i1);
+ 	S.copy(S.get_t_x_sing(i2), t_x2); t_gamma2 = S.get_t_gamma_sing(i2);
+       } else {
+ 	S.fill_random(T_x); T_gamma = S.random();
+ 	no = S.w_norm(T_x, T_gamma);
+ 	S.scaled_add(t_x2, T_x, 0.1/no, t_x2);
+ 	t_gamma2 += 0.1/no * T_gamma;
+ 	S.scaled_add(x_end, t_x2, h, X); Gamma = gamma_end + h * t_gamma2;
+ 	S.set_build(BUILD_ALL);
+ 	compute_tangent(S, X, Gamma, t_x2, t_gamma2);
+       }
+     } while (++ncomb < S.nbcomb());
+ 
+     if (S.noisy() > 0)
+       cout << "located branches " << S.nb_tangent_sing() << endl;
+   }
+ 
+ 
+   template <typename CONT_S, typename VECT>
+   void init_test_function(CONT_S &S, const VECT &x, double gamma,
+ 			  const VECT &t_x, double t_gamma) {
+     if (S.noisy() > 0) cout << "starting computing an initial value of a "
+ 			    << "test function for bifurcations" << endl;
+     S.set_build(BUILD_ALL);
++>>>>>>> upstream
      double tau = test_function(S, x, gamma, t_x, t_gamma); S.set_tau2(tau);
    }
  
@@@ -209,32 -530,27 +670,56 @@@
  				       double &t_gamma, double &h) {
      S.set_build(BUILD_ALL);
      S.clear(t_x); t_gamma = (t_gamma >= 0) ? 1. : -1.;
++<<<<<<< HEAD
 +    if (S.noisy() > 0) cout << "computing initial tangent" << endl;
 +    compute_tangent(S, x, gamma, t_x, t_gamma);
 +    h = S.h_init();
 +    init_test_function(S, x, gamma, t_x, t_gamma);
 +  }
 +
 +  
 +  /* Perform one step of the Moore-Penrose continuation. If a new point 
 +     (x, gamma) is found, it has to be saved in the model in the end! */
 +  template <typename CONT_S, typename VECT>
 +    void Moore_Penrose_continuation(CONT_S &S, VECT &x, double &gamma,
 +				    VECT &t_x, double &t_gamma, double &h) {
 +    bool bifurcation_detected = false, converged, finished = false;
 +    int tangent_status = 0;
 +      /* 0: no manipulation with tangent direction (so far);
 +	 1: current direction neither admitted nor rejected;
 +	 2: direction rejected;
 +	 3: direction admitted with plus sign;
 +	 4: direction admitted with minus sign; */
 +    unsigned long it, step_dec = 0;
 +    double t_gamma0 = t_gamma,
 +      Delta_Gamma, Gamma, T_gamma, r, no, res, diff, ang;
 +    VECT t_x0(t_x), F(x), g(x), Delta_X(x), X(x), T_x(x), y(x);
 +
 +    do { // step control
 +
++=======
+     if (S.noisy() > 0)
+       cout << "starting computing an initial tangent" << endl;
+     compute_tangent(S, x, gamma, t_x, t_gamma);
+     h = S.h_init();
+     if (S.bifurcations()) init_test_function(S, x, gamma, t_x, t_gamma);
+   }
+ 
+   
+   /* Perform one step of the (non-smooth) Moore-Penrose continuation.
+      NOTE: The new point need not to be saved in the model in the end! */
+   template <typename CONT_S, typename VECT>
+     void Moore_Penrose_continuation(CONT_S &S, VECT &x, double &gamma,
+ 				    VECT &t_x, double &t_gamma, double &h) {
+     bool converged, new_point = false, tangent_switched = false;
+     unsigned long it, step_dec = 0;
+     double t_gamma0 = t_gamma, Gamma, T_gamma;
+     VECT t_x0(t_x), X(x), T_x(x);
+ 
+     S.clear_tau_currentstep(); S.clear_sing_data();
+ 
+     do {
++>>>>>>> upstream
        // prediction
        if (S.noisy() > 0) cout << "prediction with h = " << h << endl;
        S.scaled_add(x, t_x, h, X); Gamma = gamma + h * t_gamma;
@@@ -242,116 -558,92 +727,205 @@@
        S.copy(t_x, T_x); T_gamma = t_gamma;
        
        // correction
++<<<<<<< HEAD
 +      if (S.noisy() > 0) cout << "starting correction " << endl;
 +      it = 0;
 +      S.F(X, Gamma, F);
 +      
 +      do { // Newton iterations
 +	S.F_gamma(X, Gamma, g);
 +	S.solve_grad(X, Gamma, Delta_X, y, F, g);
 +	r = w_sp_(S, T_x, y);
 +
 +	Delta_Gamma = w_sp_(S, T_x, Delta_X) / (r - T_gamma);
 +	S.scaled_add(Delta_X, y, -Delta_Gamma, Delta_X);
 +	S.scaled_add(X, Delta_X, -1., X); Gamma -= Delta_Gamma;
 +	S.set_build(BUILD_ALL);
 +	
 +	T_gamma = 1. / (T_gamma - r);
 +	S.scale(y, -T_gamma); S.copy(y, T_x);
 +	no = norm_(S, T_x, T_gamma);
 +	S.scale(T_x, 1./no); T_gamma /= no;
 +
 +	S.F(X, Gamma, F); res = norm_(S, F); 
 +	diff = norm_(S, Delta_X, Delta_Gamma);
 +	converged = (res <= S.maxres() && diff <= S.maxdiff());
 +	it++;
 +
 +	if (S.noisy() > 1)
 +	  cout << "iter " << it << " residual " << res
 +	       << " difference " << diff
 +	       << " cos " << sp_(S, t_x, T_x, t_gamma, T_gamma) << endl;
 +
 +      } while (!converged && it < S.maxit() && res < 1.e8);
 +
 +      if (converged) {
 +	ang = sp_(S, t_x, T_x, t_gamma, T_gamma);
 +	if (S.noisy() > 0) cout << "cos " << ang << endl;
 +// 	if (S.noisy() > 1) {
 +// 	  S.F_gamma(X, Gamma, g);
 +// 	  S.update_matrix(X, Gamma); S.mult_grad(X, Gamma, T_x, y);
 +// 	  S.scaled_add(y, g, T_gamma, y);
 +// 	  cout << "final tangent computed with the residual "
 +// 	       << norm_(S, y) << endl;
 +// 	}
 +	if (ang >= S.minang()) { // accept the new couple
 +	  S.clear_tau_hist();
 +	  if (tangent_status == 0)
 +	    bifurcation_detected =
 +	      test_smooth_bifurcation(S, X, Gamma, T_x, T_gamma);
 +	  else {
 +	    bifurcation_detected = test_nonsmooth_bifurcation
 +	      (S, x, gamma, t_x0, t_gamma0, X, Gamma, T_x, T_gamma);
 +	  }
 +	  if (bifurcation_detected) cout << "Bifurcation detected!" << endl;
 +	  if (step_dec == 0 && it < S.thrit()) // elongate the step size
 +	    h = (S.h_inc() * h < S.h_max()) ? S.h_inc() * h : S.h_max();
 +	  finished = true;
 +	}
 +      }
 +      
 +      if (!finished) {
 +	if (h > S.h_min()) { // diminish the step size
 +	  h = (S.h_dec() * h > S.h_min()) ? S.h_dec() * h : S.h_min();
 +	  step_dec++;
 +	}
 +	else if (tangent_status == 0) {
 +	  if (S.noisy() > 1)
 +	    cout << "Seeking a new tangent direction" << endl;
 +	  unsigned long tan = 0;
 +	  S.copy(t_x, T_x); T_gamma = t_gamma;
 +	  S.scaled_add(x, T_x, h, X); Gamma = gamma + h * T_gamma;
 +	  S.set_build(BUILD_ALL);
 +	  compute_tangent(S, X, Gamma, T_x, T_gamma);
 +
 +	  do { // seek a new tangent
 +	    if (S.noisy() > 1)
 +	      cout << "Trying direction " << tan + 1 << endl;
 +	    h = S.h_min();
 +
 +	    do { // test (T_x, T_gamma)
 +	      tangent_status =
 +		test_direction(S, x, gamma, t_x, t_gamma, T_x, T_gamma, h);
 +	      if (tangent_status == 1) {
 +		h *= -1.;
 +		tangent_status =
 +		  test_direction(S, x, gamma, t_x, t_gamma, T_x, T_gamma, h);
 +	        h *= -2.;
 +	      }
 +	    } while (tangent_status == 1 && h <= 1e5);
 +
 +	    tan++;
 +	  } while (tangent_status <= 2 && tan < 1); // tan >= 1?
 +	  
 +	  if (tangent_status >= 3) {
 +	    if (S.noisy() > 1)
 +	      cout << "Direction " << tan << " accepted" << endl;
 +	    S.copy(T_x, t_x); t_gamma = T_gamma;
 +	    if (tangent_status == 4) { 
 +	      S.scale(t_x, -1.); t_gamma *= -1.; h /= 2.;
 +	    }
 +	    h = (h < S.h_init()) ? S.h_init() : h; step_dec = 0;
 +	  } else break;
 +	} else break;
 +      }
 +    } while (!finished);
 +
 +    if (finished) {
 +      S.copy(X, x); gamma = Gamma;
 +      S.copy(T_x, t_x); t_gamma = T_gamma;
 +    } else h = 0;
 +  }
 +
 +
++=======
+       converged = newton_corr(S, X, Gamma, T_x, T_gamma, t_x, t_gamma, it);
+ 
+       if (converged
+ 	  && (S.cosang(T_x, t_x, T_gamma, t_gamma) >= S.mincos())) {
+ 	new_point = true;
+ 	if (S.bifurcations()) {
+ 	  if (S.noisy() > 0)
+ 	    cout << "new point found, starting computing a test function "
+ 		 << "for bifurcations" << endl;
+ 	  if (!tangent_switched) {
+ 	    if(test_smooth_bifurcation(S, X, Gamma, T_x, T_gamma)) {
+ 	      S.set_sing_label("smooth bifurcation point");
+ 	      if (S.noisy() > 0)
+ 		cout << "Smooth bifurcation point detected!" << endl;
+ 	      treat_smooth_bif_point(S, X, Gamma, T_x, T_gamma, h);
+ 	    }
+ 	  } else if (test_nonsmooth_bifurcation(S, x, gamma, t_x0, t_gamma0,
+ 						X, Gamma, T_x, T_gamma)) {
+ 	    S.set_sing_label("non-smooth bifurcation point");
+ 	    if (S.noisy() > 0)
+ 	      cout << "Non-smooth bifurcation point detected!" << endl;
+ 	    treat_nonsmooth_point(S, x, gamma, t_x0, t_gamma0, 0);
+ 	  }
+ 	}
+ 	
+ 	if (step_dec == 0 && it < S.thrit())
+ 	  h = (S.h_inc() * h < S.h_max()) ? S.h_inc() * h : S.h_max();
+       } else if (h > S.h_min()) {
+ 	h = (S.h_dec() * h > S.h_min()) ? S.h_dec() * h : S.h_min();
+ 	step_dec++;
+       } else if (S.non_smooth() && !tangent_switched) {
+ 	if (S.noisy() > 0)
+ 	  cout << "classical continuation has failed" << endl;
+ 	if (switch_tangent(S, x, gamma, t_x, t_gamma, h)) {
+ 	  tangent_switched = true;
+ 	  if (S.noisy() > 0)
+ 	    cout << "restarting the classical continuation" << endl;
+ 	} else break;
+       } else break;
+     } while (!new_point);
+ 
+     if (new_point) {
+       S.copy(X, x); gamma = Gamma;
+       S.copy(T_x, t_x); t_gamma = T_gamma;
+     } else if (S.non_smooth()) {
+       treat_nonsmooth_point(S, x, gamma, t_x0, t_gamma0, 1);
+       if (S.next_point()) {
+ 	if (S.bifurcations()) {
+ 	  if (S.noisy() > 0)
+ 	    cout << "starting computing a test function for bifurcations"
+ 		 << endl;
+ 	  S.set_build(BUILD_ALL);
+ 	  bool bifurcation_detected = (S.nb_tangent_sing() > 2);
+ 	  if (bifurcation_detected) {
+ 	    // update the stored values of the test function only
+ 	    S.set_tau1(tau_init);
+ 	    S.set_tau2(test_function(S, S.get_x_next(), S.get_gamma_next(),
+ 				     S.get_t_x_sing(1),
+ 				     S.get_t_gamma_sing(1)));
+ 	  } else
+ 	    bifurcation_detected
+ 	      = test_nonsmooth_bifurcation(S, x, gamma, t_x, t_gamma,
+ 					   S.get_x_next(),
+ 					   S.get_gamma_next(),
+ 					   S.get_t_x_sing(1),
+ 					   S.get_t_gamma_sing(1));
+ 	  if (bifurcation_detected) {
+ 	    S.set_sing_label("non-smooth bifurcation point");
+ 	    if (S.noisy() > 0)
+ 	      cout << "Non-smooth bifurcation point detected!" << endl;
+ 	  }
+ 	}
+ 	
+ 	S.copy(S.get_x_next(), x); gamma = S.get_gamma_next();
+ 	S.copy(S.get_t_x_sing(1), t_x); t_gamma = S.get_t_gamma_sing(1);
+ 	h = S.h_init();
+ 	new_point = true;
+       }
+     }
+     
+     if (!new_point) {
+       cout << "Continuation has failed!" << endl;
+       h = 0;
+     }
+   }
+   
++>>>>>>> upstream
  
    //=========================================================================
    // Moore-Penrose continuation method for Getfem models
@@@ -366,68 -658,93 +940,156 @@@
      typedef model_real_sparse_matrix MAT;
      
    private:
++<<<<<<< HEAD
 +    model *md;  // for real models only
 +    std::string parameter_name_;
 +    rmodel_plsolver_type lsolver;
 +    double scfac_;
 +    unsigned long maxit_, thrit_;
 +    double maxres_, maxdiff_, minang_, h_init_, h_max_, h_min_, h_inc_,
 +      h_dec_, epsilon_, maxres_solve_;
 +    int noisy_;
 +    unsigned long nb_test_;
 +    bool with_parametrized_data;
 +    std::string initdata_name_, finaldata_name_, currentdata_name_;
 +    build_data build;
 +    double tau1_, tau2_;
 +    VECT tau_hist;
 +    VECT b_x_, c_x_;
 +    double b_gamma_, c_gamma_, d_;
 +
 +  public:
 +    cont_struct_getfem_model
 +    (model &m, const std::string &pn, rmodel_plsolver_type ls, double sfac,
 +     unsigned long mit = 10, unsigned long tit = 8, double mres = 1.e-6,
 +     double mdiff = 1.e-9, double mang = 0.9, double hin = 1.e-2,
 +     double hmax = 1.e-1, double hmin = 1.e-5, double hinc = 1.3,
 +     double hdec = 0.5, double eps = 1.e-8, double mress = 1.e-7,
 +     int noi = 0, unsigned long ntest = 50)
 +      : md(&m), parameter_name_(pn), lsolver(ls), scfac_(sfac), maxit_(mit),
 +	thrit_(tit), maxres_(mres), maxdiff_(mdiff), minang_(mang),
 +	h_init_(hin), h_max_(hmax), h_min_(hmin), h_inc_(hinc), h_dec_(hdec),
 +	epsilon_(eps), maxres_solve_(mress), noisy_(noi), nb_test_(ntest),
 +	with_parametrized_data(false), build(BUILD_ALL), tau1_(tau_init),
 +	tau2_(tau_init), tau_hist(0)
 +    {}
 +    
 +    cont_struct_getfem_model
 +    (model &m, const std::string &pn, const std::string &in,
 +     const std::string &fn, const std::string &cn, rmodel_plsolver_type ls,
 +     double sfac, unsigned long mit = 10, unsigned long tit = 8,
 +     double mres = 1.e-6, double mdiff = 1.e-9, double mang = 0.9,
 +     double hin = 1.e-2, double hmax = 1.e-1, double hmin = 1.e-5,
 +     double hinc = 1.3, double hdec = 0.5, double eps = 1.e-8,
 +     double mress = 1.e-7, int noi = 0, unsigned long ntest = 50)
 +      : md(&m), parameter_name_(pn), lsolver(ls), scfac_(sfac), maxit_(mit),
 +	thrit_(tit), maxres_(mres), maxdiff_(mdiff), minang_(mang),
 +	h_init_(hin), h_max_(hmax), h_min_(hmin), h_inc_(hinc), h_dec_(hdec),
 +	epsilon_(eps), maxres_solve_(mress), noisy_(noi), nb_test_(ntest),
 +	with_parametrized_data(true), initdata_name_(in),
 +	finaldata_name_(fn), currentdata_name_(cn), build(BUILD_ALL),
 +	tau1_(tau_init), tau2_(tau_init), tau_hist(0)
 +    {}
++=======
+     model *md;
+     bool bifurcations_, nonsmooth;
+     std::string parameter_name_;
+     bool with_parametrised_data;
+     std::string initdata_name_, finaldata_name_, currentdata_name_;
+     double scfac_;
+     rmodel_plsolver_type lsolver;
+     double h_init_, h_max_, h_min_, h_inc_, h_dec_;
+     unsigned long maxit_, thrit_;
+     double maxres_, maxdiff_, mincos_, maxres_solve_, delta_max_, delta_min_,
+       thrvar_;
+     unsigned long nbdir_, nbcomb_;
+     int noisy_;
+     VECT b_x_, c_x_;
+     double b_gamma_, c_gamma_, d_;
+     double tau1, tau2;
+     VECT alpha_hist, tau_hist;
+     std::map<double, double> tau_graph;
+     std::string sing_label;
+     VECT x_sing, x_next;
+     double gamma_sing, gamma_next;
+     std::vector<VECT> t_x_sing, t_x_predict;
+     std::vector<double> t_gamma_sing, t_gamma_predict;
+     build_data build;
+ 
+   public:
+     void init_border(void) {
+       srand(unsigned(time(NULL)));
+       unsigned long nbdof = md->nb_dof();
+       gmm::resize(b_x_, nbdof); gmm::fill_random(b_x_);
+       gmm::resize(c_x_, nbdof); gmm::fill_random(c_x_);
+       b_gamma_ = gmm::random(1.); c_gamma_ = gmm::random(1.);
+       d_ = gmm::random(1.);
+     }
+ 
+     cont_struct_getfem_model
+     (model &m, const std::string &pn, double sfac, rmodel_plsolver_type ls,
+      bool bif = false, double hin = 1.e-2, double hmax = 1.e-1,
+      double hmin = 1.e-5, double hinc = 1.3, double hdec = 0.5,
+      unsigned long mit = 10, unsigned long tit = 4, double mres = 1.e-6,
+      double mdiff = 1.e-6, double mcos = 0.9, double mress = 1.e-8,
+      int noi = 0, bool nonsm = false, double dmax = 0.005,
+      double dmin = 0.00012, double tvar = 0.02, unsigned long ndir = 40,
+      unsigned long ncomb = 1)
+       : md(&m), bifurcations_(bif), nonsmooth(nonsm), parameter_name_(pn),
+ 	with_parametrised_data(false), scfac_(sfac), lsolver(ls),
+ 	h_init_(hin), h_max_(hmax), h_min_(hmin), h_inc_(hinc), h_dec_(hdec),
+ 	maxit_(mit), thrit_(tit), maxres_(mres), maxdiff_(mdiff),
+ 	mincos_(mcos), maxres_solve_(mress), delta_max_(dmax),
+ 	delta_min_(dmin), thrvar_(tvar), nbdir_(ndir), nbcomb_(ncomb),
+ 	noisy_(noi), tau1(tau_init), tau2(tau_init), gamma_sing(0.),
+ 	gamma_next(0.), build(BUILD_ALL)
+     { GMM_ASSERT1(!md->is_complex(),
+ 		  "Continuation has only a real version, sorry.");
+       if (bifurcations_) init_border(); }
+     
+     cont_struct_getfem_model
+     (model &m, const std::string &pn, const std::string &in,
+      const std::string &fn, const std::string &cn, double sfac,
+      rmodel_plsolver_type ls, bool bif = false, double hin = 1.e-2,
+      double hmax = 1.e-1, double hmin = 1.e-5, double hinc = 1.3,
+      double hdec = 0.5, unsigned long mit = 10, unsigned long tit = 4,
+      double mres = 1.e-6, double mdiff = 1.e-6, double mcos = 0.9,
+      double mress = 1.e-8, int noi = 0, bool nonsm = false,
+      double dmax = 0.005, double dmin = 0.00012, double tvar = 0.02,
+      unsigned long ndir = 40, unsigned long ncomb = 1)
+       : md(&m), bifurcations_(bif), nonsmooth(nonsm), parameter_name_(pn),
+ 	with_parametrised_data(true), initdata_name_(in),
+ 	finaldata_name_(fn), currentdata_name_(cn), scfac_(sfac),
+ 	lsolver(ls), h_init_(hin), h_max_(hmax), h_min_(hmin), h_inc_(hinc),
+ 	h_dec_(hdec), maxit_(mit), thrit_(tit), maxres_(mres),
+ 	maxdiff_(mdiff), mincos_(mcos), maxres_solve_(mress),
+ 	delta_max_(dmax), delta_min_(dmin), thrvar_(tvar), nbdir_(ndir),
+ 	nbcomb_(ncomb), noisy_(noi), tau1(tau_init), tau2(tau_init),
+ 	gamma_sing(0.), gamma_next(0.), build(BUILD_ALL)
+     { GMM_ASSERT1(!md->is_complex(),
+ 		  "Continuation has only a real version, sorry.");
+       if (bifurcations_) init_border(); }
++>>>>>>> upstream
  
      cont_struct_getfem_model(void) {}
      
  
      // Linear algebra functions
++<<<<<<< HEAD
 +    double abs(double a)
 +    { return gmm::abs(a); }
 +    void clear(VECT &v)
 +    { gmm::clear(v); }
 +    void copy(const VECT &v1, VECT &v)
 +    { gmm::copy(v1, v); }
 +    void scale(VECT &v, double a)
 +    { gmm::scale(v, a); }
++=======
+     double abs(double a) { return gmm::abs(a); }
+     void clear(VECT &v) { gmm::clear(v); }
+     void copy(const VECT &v1, VECT &v) { gmm::copy(v1, v); }
+     void scale(VECT &v, double a) { gmm::scale(v, a); }
++>>>>>>> upstream
      void scaled_add(const VECT &v1, const VECT &v2, double a, VECT &v)
      { gmm::add(v1, gmm::scaled(v2, a), v); }
      void scaled_add(const VECT &v1, double a1,
@@@ -435,33 -752,51 +1097,78 @@@
      { gmm::add(gmm::scaled(v1, a1), gmm::scaled(v2, a2), v); }
      void scaled_add(const MAT &M1, double a1,
  		    const MAT &M2, double a2, MAT &M)
++<<<<<<< HEAD
 +    { gmm::add(gmm::scaled(M1, a1), gmm::scaled(M2, a2), M); }
 +    double sp(const VECT &v1, const VECT &v2)
 +    { return gmm::vect_sp(v1, v2); }
 +    void mult(const MAT &A, const VECT &v1, VECT &v)
 +    { gmm::mult(A, v1, v); }
 +
 +    void solve(const MAT &A, VECT &g, const VECT &L) { // A * g = L
 +      if (noisy_ > 1) cout << "starting linear solver" << endl;
 +      gmm::iteration iter(maxres_solve_, noisy_, 40000);
 +      (*lsolver)(A, g, L, iter);
 +      if (noisy_ > 1) cout << "linear solver done" << endl;
 +    }
 +
 +    void solve(const MAT &A, VECT &g1, VECT &g2,
 +	       const VECT &L1, const VECT &L2) { // A * (g1|g2) = (L1|L2)
 +      if (noisy_ > 1) cout << "starting linear solver" << endl;
 +      gmm::iteration iter(maxres_solve_, noisy_, 40000);
 +      (*lsolver)(A, g1, L1, iter);
 +      iter.init(); (*lsolver)(A, g2, L2, iter); // (can be optimised)
 +      if (noisy_ > 1) cout << "linear solver done" << endl;
++=======
+     { gmm::add(gmm::scaled(M1, a1), gmm::scaled(M2, a2), M); }    
+     void mult(const MAT &A, const VECT &v1, VECT &v)
+     { gmm::mult(A, v1, v); }
+ 
+     double sp(const VECT &v1, const VECT &v2)
+     { return gmm::vect_sp(v1, v2); }
+     double norm(const VECT &v)
+     { return gmm::vect_norm2(v); }
+     double w_sp(const VECT &v1, const VECT &v2)
+     { return scfac_ * gmm::vect_sp(v1, v2); }
+     double sp(const VECT &v1, const VECT &v2, double w1, double w2)
+     { return sp(v1, v2) + w1 * w2; }
+     double w_norm(const VECT &v, double w)
+     { return sqrt(w_sp(v, v) + w * w); }
+     double cosang(const VECT &v1, const VECT &v2, double w1, double w2) {
+       double no = sqrt(sp(v1, v1, w1, w1) * sp(v2, v2, w2, w2)); 
+       return ((no == 0) ? 0. : sp(v1, v2, w1, w2) / no);
+     }
+     
+     double random(void) { return gmm::random(1.); }
+     void fill_random(VECT &v) { gmm::fill_random(v); }
+ 
+     void solve(const MAT &A, VECT &g, const VECT &L) { /* A * g = L */
+       if (noisy_ > 2) cout << "starting linear solver" << endl;
+       gmm::iteration iter(maxres_solve_, (noisy_ >= 2) ? noisy_ - 2 : 0,
+ 			  40000);
+       (*lsolver)(A, g, L, iter);
+       if (noisy_ > 2) cout << "linear solver done" << endl;
+     }
+ 
+     void solve(const MAT &A, VECT &g1, VECT &g2,
+ 	       const VECT &L1, const VECT &L2) { /* A * (g1|g2) = (L1|L2) */
+       if (noisy_ > 2) cout << "starting linear solver" << endl;
+       gmm::iteration iter(maxres_solve_, (noisy_ >= 2) ? noisy_ - 2 : 0,
+ 			  40000);
+       (*lsolver)(A, g1, L1, iter);
+       iter.init(); (*lsolver)(A, g2, L2, iter); // (can be optimised)
+       if (noisy_ > 2) cout << "linear solver done" << endl;
++>>>>>>> upstream
      }
  
  
      // Evaluation of  ...
      void set_variables(const VECT &x, double gamma) {
        md->set_real_variable(parameter_name_)[0] = gamma;
++<<<<<<< HEAD
 +      if (with_parametrized_data) {
++=======
+       if (with_parametrised_data) {
++>>>>>>> upstream
  	gmm::add(gmm::scaled(md->real_variable(initdata_name_), 1. - gamma),
  		 gmm::scaled(md->real_variable(finaldata_name_), gamma),
  		 md->set_real_variable(currentdata_name_));
@@@ -479,19 -814,20 +1186,34 @@@
        gmm::copy(gmm::scaled(md->real_rhs(), -1.), f);
      }
      
++<<<<<<< HEAD
 +    // (F(x, gamma + epsilon_) - F(x, gamma)) / epsilon_ --> g
 +    void F_gamma(const VECT &x, double gamma, VECT &g) {
 +      VECT F0(x), F1(x);
 +      F(x, gamma, F0);
 +      build = BUILD_ALL; F(x, gamma + epsilon_, F1); build = BUILD_ALL;
 +      gmm::add(F1, gmm::scaled(F0, -1.), g);
 +      gmm::scale(g, 1./epsilon_);
++=======
+     // (F(x, gamma + eps) - F(x, gamma)) / eps --> g
+     void F_gamma(const VECT &x, double gamma, VECT &g) {
+       const double eps = 1.e-8;
+       VECT F0(x), F1(x);
+       F(x, gamma, F0);
+       build = BUILD_ALL; F(x, gamma + eps, F1); build = BUILD_ALL;
+       gmm::add(F1, gmm::scaled(F0, -1.), g);
+       gmm::scale(g, 1./eps);
++>>>>>>> upstream
      }
  
      void update_matrix(const VECT &x, double gamma) {
        if (build == BUILD_ALL) set_variables(x, gamma);
        if (build & BUILD_F_x) {
++<<<<<<< HEAD
 +	if (noisy_ > 1) cout << "starting computing tangent matrix" << endl;
++=======
+ 	if (noisy_ > 2) cout << "starting computing tangent matrix" << endl;
++>>>>>>> upstream
  	md->assembly(model::BUILD_MATRIX);
  	build = build_data(build ^ BUILD_F_x);
        }
@@@ -526,52 -862,126 +1248,170 @@@
      }
  
      
++<<<<<<< HEAD
 +    // Misc.
 +    model &linked_model(void) { return *md; }
 +    std::string parameter_name(void) { return parameter_name_; }
 +    double scfac(void) { return scfac_; }
 +    unsigned long thrit(void) { return thrit_; }
 +    unsigned long maxit(void) { return maxit_; }
 +    double epsilon(void) { return epsilon_; }
 +    double minang(void) { return minang_; }
 +    double maxres(void) { return maxres_; }
 +    double maxdiff(void) { return maxdiff_; }
++=======
+     // Misc. for accessing private data
+     model &linked_model(void) { return *md; }
+     bool bifurcations(void) { return bifurcations_; }
+     bool non_smooth(void) { return nonsmooth; }
+     std::string parameter_name(void) { return parameter_name_; }
+     double scfac(void) { return scfac_; }
++>>>>>>> upstream
      double h_init(void) { return h_init_; }
      double h_min(void) { return h_min_; }
      double h_max(void) { return h_max_; }
      double h_dec(void) { return h_dec_; }
      double h_inc(void) { return h_inc_; }
++<<<<<<< HEAD
 +    int noisy(void) { return noisy_; }
 +    unsigned long nb_test(void) { return nb_test_; }
 +    void set_build(build_data build_) { build = build_; }
 +    void set_tau1(double tau) { tau1_ = tau; }
 +    double tau1(void) { return tau1_; }
 +    void set_tau2(double tau) { tau2_ = tau; }
 +    double tau2(void) { return tau2_; }
 +
 +    void init_border(const VECT &v) {
 +      srand(unsigned(time(NULL)));
 +      gmm::resize(b_x_, gmm::vect_size(v)); gmm::fill_random(b_x_);
 +      gmm::resize(c_x_, gmm::vect_size(v)); gmm::fill_random(c_x_);
 +      b_gamma_ = gmm::random(1.); c_gamma_ = gmm::random(1.);
 +      d_ = gmm::random(1.);
 +    }
++=======
+     unsigned long maxit(void) { return maxit_; }
+     unsigned long thrit(void) { return thrit_; }
+     double maxres(void) { return maxres_; }
+     double maxdiff(void) { return maxdiff_; }
+     double mincos(void) { return mincos_; }
+     double delta_max(void) { return delta_max_; }
+     double delta_min(void) { return delta_min_; }
+     double thrvar(void) { return thrvar_; }
+     unsigned long nbdir(void) { return nbdir_; }
+     unsigned long nbcomb(void) { return nbcomb_; }
+     int noisy(void) { return noisy_; }
++>>>>>>> upstream
      VECT &b_x(void) { return b_x_; }
      VECT &c_x(void) { return c_x_; }
      double b_gamma(void) { return b_gamma_; }
      double c_gamma(void) { return c_gamma_; }
      double d(void) { return d_; }
  
++<<<<<<< HEAD
 +    void clear_tau_hist(void) { gmm::resize(tau_hist, 0); }
 +    void init_tau_hist(void) {
 +      gmm::resize(tau_hist, nb_test_ + 1);
 +      tau_hist[0] = tau2_;
 +    }
 +    void set_tau_hist(unsigned long i, double a) {
 +      GMM_ASSERT2(i < nb_test_ + 1, "out of range");
 +      tau_hist[i] = a;
 +    }
 +    VECT &get_tau_hist(void) { return tau_hist; }
++=======
+     void set_tau1(double tau) { tau1 = tau; }
+     double get_tau1(void) { return tau1; }
+     void set_tau2(double tau) { tau2 = tau; }
+     double get_tau2(void) { return tau2; }
+     void clear_tau_currentstep(void) {
+       tau_graph.clear();
+       gmm::resize(alpha_hist, 0); gmm::resize(tau_hist, 0);
+     }
+     void init_tau_graph(void) { tau_graph[0.] = tau2; }
+     void insert_tau_graph(double alpha, double tau) {
+       tau_graph[alpha] = tau;
+     }
+     VECT &get_alpha_hist(void) {
+       unsigned long i = 0;
+       gmm::resize(alpha_hist, tau_graph.size());
+       for (std::map<double, double>::iterator it = tau_graph.begin();
+ 	   it != tau_graph.end(); it++) {
+ 	alpha_hist[i] = (*it).first; i++;
+       }	
+       return alpha_hist;
+     }
+     VECT &get_tau_hist(void) {
+       unsigned long i = 0;
+       gmm::resize(tau_hist, tau_graph.size());
+       for (std::map<double, double>::iterator it = tau_graph.begin();
+ 	   it != tau_graph.end(); it++) {
+ 	tau_hist[i] = (*it).second; i++; 
+       }	
+       return tau_hist;
+     }
+ 
+     void clear_sing_data(void) {
+       sing_label = "";
+       gmm::resize(x_sing, 0); gmm::resize(x_next, 0);
+       t_x_sing.clear(); t_gamma_sing.clear();
+       t_x_predict.clear(); t_gamma_predict.clear();
+     }
+     void set_sing_label(std::string label) { sing_label = label; }
+     std::string get_sing_label(void) { return sing_label; }
+     void set_sing_point(const VECT &x, double gamma) {
+       gmm::resize(x_sing, gmm::vect_size(x)); gmm::copy(x, x_sing);
+       gamma_sing = gamma;
+     }
+     VECT &get_x_sing(void) { return x_sing; }
+     double get_gamma_sing(void) { return gamma_sing; }
+     unsigned long nb_tangent_sing(void) { return t_x_sing.size(); }
+     bool insert_tangent_sing(const VECT &t_x, double t_gamma){
+       bool is_included = false;
+       unsigned long i = 0;
+       double cang;
+       while ((i < t_x_sing.size()) && (!is_included)){
+ 	cang = cosang(t_x_sing[i], t_x, t_gamma_sing[i], t_gamma);
+ 	is_included = (cang >= mincos_);
+ 	++i;
+       }
+       if (!is_included) {
+ 	t_x_sing.push_back(t_x); t_gamma_sing.push_back(t_gamma);
+       }
+       return !is_included;
+     }
+     VECT &get_t_x_sing(unsigned long i) { return t_x_sing[i]; }
+     double get_t_gamma_sing(unsigned long i) { return t_gamma_sing[i]; }
+     std::vector<VECT> &get_t_x_sing(void) { return t_x_sing; }
+     std::vector<double> &get_t_gamma_sing(void) { return t_gamma_sing; }
+ 
+     bool next_point(void) { return gmm::vect_size(x_next) > 0; }
+     void set_next_point(const VECT &x, double gamma) {
+       if (gmm::vect_size(x_next) == 0) {
+ 	gmm::resize(x_next, gmm::vect_size(x)); gmm::copy(x, x_next);
+ 	gamma_next = gamma;
+       }
+     }
+     VECT &get_x_next(void) { return x_next; }
+     double get_gamma_next(void) { return gamma_next; }
+ 
+     bool insert_tangent_predict(const VECT &t_x, double t_gamma){
+       bool is_included = false;
+       unsigned long i = 0;
+       double cang;
+       while ((i < t_x_predict.size()) && (!is_included)){
+ 	cang = gmm::abs(cosang(t_x_predict[i], t_x,
+ 			       t_gamma_predict[i], t_gamma));
+ 	is_included = (cang >= mincos_);
+ 	++i;
+       }
+       if (!is_included) {
+ 	t_x_predict.push_back(t_x); t_gamma_predict.push_back(t_gamma);
+       }
+       return !is_included;
+     }
+ 
+     void set_build(build_data build_) { build = build_; }
++>>>>>>> upstream
    };
  
  #endif
diff --cc src/getfem/getfem_fem.h
index 48eb376,1b4d011..913ae9f
--- a/src/getfem/getfem_fem.h
+++ b/src/getfem/getfem_fem.h
@@@ -495,7 -495,7 +495,11 @@@ namespace getfem 
        size_type R = nb_base_components(0);
        base_tensor::iterator it = t.begin();
        for (size_type  i = 0; i < R; ++i, ++it)
++<<<<<<< HEAD
 +        *it = base_[i].eval(x.begin());
++=======
+         *it = bgeot::to_scalar(base_[i].eval(x.begin()));
++>>>>>>> upstream
      }
      void grad_base_value(const base_node &x, base_tensor &t) const {
        bgeot::multi_index mi(3);
@@@ -506,7 -506,7 +510,11 @@@
        base_tensor::iterator it = t.begin();
        for (dim_type j = 0; j < n; ++j)
          for (size_type i = 0; i < R; ++i, ++it)
++<<<<<<< HEAD
 +          { FUNC f = base_[i]; f.derivative(j); *it = f.eval(x.begin()); }
++=======
+           { FUNC f = base_[i]; f.derivative(j); *it = bgeot::to_scalar(f.eval(x.begin())); }
++>>>>>>> upstream
      }
      void hess_base_value(const base_node &x, base_tensor &t) const {
        bgeot::multi_index mi(4);
@@@ -521,7 -521,7 +529,11 @@@
            for (size_type i = 0; i < R; ++i, ++it) {
              FUNC f = base_[i];
              f.derivative(j); f.derivative(k);
++<<<<<<< HEAD
 +            *it = f.eval(x.begin());
++=======
+             *it = bgeot::to_scalar(f.eval(x.begin()));
++>>>>>>> upstream
            }
      }
  
@@@ -667,7 -667,7 +679,11 @@@
      mutable base_matrix M_; // optional transformation matrix (for non tau-equivalent fems)
      pfem pf_;               // current fem
      pfem_precomp pfp_;      // optional fem_precomp_ (speed up the computations)
++<<<<<<< HEAD
 +    size_type convex_num_;  // the convex number (info needed by some specific FEMs)
++=======
+     size_type convex_num_;  // The element (convex) number
++>>>>>>> upstream
      size_type face_num_;    // Face number for boundary integration
    public:
      /// true if a fem_precomp_ has been supplied.
@@@ -763,7 -763,7 +779,11 @@@
    void virtual_fem::interpolation_grad(const fem_interpolation_context& c,
                                         const CVEC& coeff, VMAT &val,
                                         dim_type Qdim) const {
++<<<<<<< HEAD
 +    typedef typename gmm::linalg_traits<CVEC>::value_type T;
++=======
+     // typedef typename gmm::linalg_traits<CVEC>::value_type T;
++>>>>>>> upstream
      size_type Qmult = size_type(Qdim) / target_dim();
      dim_type N = dim_type(c.N());
      GMM_ASSERT1(gmm::mat_ncols(val) == N && gmm::mat_nrows(val) == Qdim,
@@@ -788,7 -788,7 +808,11 @@@
    void virtual_fem::interpolation_hess(const fem_interpolation_context& c,
                                         const CVEC& coeff, VMAT &val,
                                         dim_type Qdim) const {
++<<<<<<< HEAD
 +    typedef typename gmm::linalg_traits<CVEC>::value_type T;
++=======
+     //    typedef typename gmm::linalg_traits<CVEC>::value_type T;
++>>>>>>> upstream
      size_type Qmult = size_type(Qdim) / target_dim();
      dim_type N = dim_type(c.N());
      GMM_ASSERT1(gmm::mat_ncols(val) == gmm::size_type(N*N)
diff --cc src/getfem/getfem_interpolation.h
index 5e775e9,bdf6b31..23c4566
--- a/src/getfem/getfem_interpolation.h
+++ b/src/getfem/getfem_interpolation.h
@@@ -119,7 -125,7 +125,11 @@@ namespace getfem 
    inline void interpolation_function__(const mesh_fem &mf, VECT &V,
                                         F &f, const dal::bit_vector &dofs,
                                         const M &mm, gmm::abstract_matrix) {
++<<<<<<< HEAD
 +    typedef typename gmm::linalg_traits<VECT>::value_type T;
++=======
+     // typedef typename gmm::linalg_traits<VECT>::value_type T;
++>>>>>>> upstream
      size_type Nr = gmm::mat_nrows(mm), Nc = gmm::mat_ncols(mm), N = Nr*Nc;
      size_type Q = mf.get_qdim();
      base_matrix m(Nr, Nc);
@@@ -220,7 -233,9 +237,13 @@@
    template<typename VECTU, typename VECTV>
    void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target,
                       const VECTU &U, VECTV &V, int extrapolation = 0,
++<<<<<<< HEAD
 +                     double EPS = 1E-10);
++=======
+                      double EPS = 1E-10,
+                      mesh_region rg_source=mesh_region::all_convexes(),
+                      mesh_region rg_target=mesh_region::all_convexes());
++>>>>>>> upstream
  
    /**
       @brief Build the interpolation matrix of mf_source on mf_target.
@@@ -231,7 -251,9 +259,13 @@@
     */
    template<typename MAT>
    void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target,
++<<<<<<< HEAD
 +                     MAT &M, int extrapolation = 0, double EPS = 1E-10);
++=======
+                      MAT &M, int extrapolation = 0, double EPS = 1E-10,
+                      mesh_region rg_source=mesh_region::all_convexes(),
+                      mesh_region rg_target=mesh_region::all_convexes());
++>>>>>>> upstream
  
  
    /* --------------------------- Implementation ---------------------------*/
@@@ -314,14 -341,14 +353,23 @@@
        }
        for (size_type i = 0; i < nbd_t; ++i, itdof+=mf_target.get_qdim()) {
          size_type dof_t = *itdof*qmult;
++<<<<<<< HEAD
 +        if (dof_t_done.is_in(*itdof)) continue;
 +        dof_t_done.add(*itdof);
++=======
+         if (!discontinuous_source && dof_t_passes[*itdof] > 0) continue;
+         dof_t_passes[*itdof] += 1;
++>>>>>>> upstream
          ctx.set_ii(i);
          if (version == 0) {
            for (size_type qq=0; qq < qqdim; ++qq) {
              pf_s->interpolation(ctx, coeff[qq], val, qdim);
              for (size_type k=0; k < qdim; ++k)
++<<<<<<< HEAD
 +              V[(dof_t + k)*qqdim+qq] = val[k];
++=======
+               V[(dof_t + k)*qqdim+qq] += val[k];
++>>>>>>> upstream
            }
          }
          else {
@@@ -368,7 -408,8 +429,12 @@@
                       mesh_trans_inv &mti,
                       const VECTU &UU, VECTV &V, MAT &MM,
                       int version, int extrapolation = 0,
++<<<<<<< HEAD
 +                     dal::bit_vector *dof_untouched = 0) {
++=======
+                      dal::bit_vector *dof_untouched = 0,
+                      mesh_region rg_source=mesh_region::all_convexes()) {
++>>>>>>> upstream
  
      typedef typename gmm::linalg_traits<VECTU>::value_type T;
      const mesh &msh(mf_source.linked_mesh());
@@@ -417,10 -458,11 +483,18 @@@
          dof_source.assign(idct.begin(), idct.end());
        }
        for (size_type i = 0; i < itab.size(); ++i) {
++<<<<<<< HEAD
 +        size_type dof_t = itab[i];
 +        if (dof_done.is_in(dof_t)) {
 +          dof_done.sup(dof_t);
 +          ctx.set_xref(mti.reference_coords()[dof_t]);
++=======
+         size_type ipt = itab[i];
+         if (points_to_do.is_in(ipt)) {
+           points_to_do.sup(ipt);
+           ctx.set_xref(mti.reference_coords()[ipt]);
+           size_type dof_t = mti.id_of_point(ipt);
++>>>>>>> upstream
            size_type pos = dof_t * qdim_s;
            if (version == 0) {
              for (size_type qq=0; qq < qqdim; ++qq) {           
@@@ -452,13 -494,20 +526,30 @@@
          }
        }
      }
++<<<<<<< HEAD
 +    if (dof_done.card() != 0) {
 +      if (dof_untouched)
 +        *dof_untouched = dof_done;
 +      else
 +        GMM_WARNING2("in interpolation (different meshes),"
 +                     << dof_done.card() << " dof of target mesh_fem have "
 +                     << " been missed\nmissing dofs : " << dof_done);
++=======
+     if (points_to_do.card() != 0) {
+       if (dof_untouched) {
+         dof_untouched->clear();
+         for (dal::bv_visitor ipt(points_to_do); !ipt.finished(); ++ipt)
+           dof_untouched->add(mti.id_of_point(ipt));
+       }
+       else {
+         dal::bit_vector dofs_to_do;
+         for (dal::bv_visitor ipt(points_to_do); !ipt.finished(); ++ipt)
+           dofs_to_do.add(mti.id_of_point(ipt));
+         GMM_WARNING2("in interpolation (different meshes),"
+                      << dofs_to_do.card() << " dof of target mesh_fem have "
+                      << " been missed\nmissing dofs : " << dofs_to_do);
+       }
++>>>>>>> upstream
      }
  
      if (version != 0) {
@@@ -473,11 -522,12 +564,20 @@@
    template<typename VECTU, typename VECTV>
    void interpolation(const mesh_fem &mf_source, mesh_trans_inv &mti,
                       const VECTU &U, VECTV &V, int extrapolation = 0,
++<<<<<<< HEAD
 +                     dal::bit_vector *dof_untouched = 0) {
 +    base_matrix M;
 +    GMM_ASSERT1((gmm::vect_size(U) % mf_source.nb_dof()) == 0 &&
 +                gmm::vect_size(V)!=0, "Dimension of vector mismatch");
 +    interpolation(mf_source, mti, U, V, M, 0, extrapolation, dof_untouched);
++=======
+                      dal::bit_vector *dof_untouched = 0,
+                      mesh_region rg_source=mesh_region::all_convexes()) {
+     base_matrix M;
+     GMM_ASSERT1((gmm::vect_size(U) % mf_source.nb_dof()) == 0 &&
+                 gmm::vect_size(V)!=0, "Dimension of vector mismatch");
+     interpolation(mf_source, mti, U, V, M, 0, extrapolation, dof_untouched, rg_source);
++>>>>>>> upstream
    }
  
  
@@@ -488,10 -538,12 +588,19 @@@
       - the solution should be continuous..
     */
    template<typename VECTU, typename VECTV, typename MAT>
++<<<<<<< HEAD
 +    void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target,
 +                       const VECTU &U, VECTV &VV, MAT &MM,
 +                       int version, int extrapolation,
 +                       double EPS) {
++=======
+   void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target,
+                      const VECTU &U, VECTV &VV, MAT &MM,
+                      int version, int extrapolation,
+                      double EPS,
+                      mesh_region rg_source=mesh_region::all_convexes(),
+                      mesh_region rg_target=mesh_region::all_convexes()) {
++>>>>>>> upstream
  
      typedef typename gmm::linalg_traits<VECTU>::value_type T;
      dim_type qqdim = dim_type(gmm::vect_size(U)/mf_source.nb_dof());
@@@ -533,21 -593,25 +650,37 @@@
    template<typename VECTU, typename VECTV>
    void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target,
                       const VECTU &U, VECTV &V, int extrapolation,
++<<<<<<< HEAD
 +                     double EPS) {
++=======
+                      double EPS,
+                      mesh_region rg_source, mesh_region rg_target) {
++>>>>>>> upstream
      base_matrix M;
      GMM_ASSERT1((gmm::vect_size(U) % mf_source.nb_dof()) == 0
                  && (gmm::vect_size(V) % mf_target.nb_dof()) == 0
                  && gmm::vect_size(V) != 0, "Dimensions mismatch");
++<<<<<<< HEAD
 +    if (&mf_source.linked_mesh() == &mf_target.linked_mesh()) {
++=======
+     if (&mf_source.linked_mesh() == &mf_target.linked_mesh() &&
+         rg_source.id() == mesh_region::all_convexes().id() &&
+         rg_target.id() == mesh_region::all_convexes().id())
++>>>>>>> upstream
        interpolation_same_mesh(mf_source, mf_target, U, V, M, 0);
-     }
      else 
-       interpolation(mf_source, mf_target, U, V, M, 0, extrapolation, EPS);
+       interpolation(mf_source, mf_target, U, V, M, 0, extrapolation, EPS,
+                     rg_source, rg_target);
    }
  
    template<typename MAT>
    void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target,
++<<<<<<< HEAD
 +                     MAT &M, int extrapolation, double EPS) {
++=======
+                      MAT &M, int extrapolation, double EPS,
+                      mesh_region rg_source, mesh_region rg_target) {
++>>>>>>> upstream
      GMM_ASSERT1(mf_source.nb_dof() == gmm::mat_ncols(M)
                  && (gmm::mat_nrows(M) % mf_target.nb_dof()) == 0
                  && gmm::mat_nrows(M) != 0, "Dimensions mismatch");
diff --cc src/getfem/getfem_models.h
index 732baa8,8cdb3de..8085b0d
--- a/src/getfem/getfem_models.h
+++ b/src/getfem/getfem_models.h
@@@ -45,10 -46,13 +46,20 @@@ namespace getfem 
  
    class virtual_brick;
    /** type of pointer on a brick */
++<<<<<<< HEAD
 +  typedef boost::intrusive_ptr<const getfem::virtual_brick> pbrick;
 +
 +  class virtual_dispatcher;
 +  typedef boost::intrusive_ptr<const getfem::virtual_dispatcher> pdispatcher;
++=======
+   typedef boost::intrusive_ptr<const virtual_brick> pbrick;
+ 
+   class virtual_dispatcher;
+   typedef boost::intrusive_ptr<const virtual_dispatcher> pdispatcher;
+ 
+   class Neumann_elem_term;
+   typedef boost::intrusive_ptr<const Neumann_elem_term> pNeumann_elem_term;
++>>>>>>> upstream
  
    // Event management : The model has to react when something has changed in
    //    the context and ask for corresponding (linear) bricks to recompute
@@@ -122,7 -128,7 +135,11 @@@
                              * respect to another fem. */
        VDESCRFILTER_CTERM   /* Variable being the dofs of a fem on a mesh region
                              * with an additional filter with the coupling
++<<<<<<< HEAD
 +			    * termson with respect to another variable. */
++=======
+ 			    * term with respect to another variable. */
++>>>>>>> upstream
      };
  
      struct var_description {
@@@ -210,12 -215,17 +226,24 @@@
      struct term_description {
        bool is_matrix_term; // tangent matrix term or rhs term.
        bool is_symmetric;   // Term have to be symmetrized.
+       bool is_global;      // Specific global term for highly coupling bricks
        std::string var1, var2;
        term_description(const std::string &v)
++<<<<<<< HEAD
 +        : is_matrix_term(false), is_symmetric(false), var1(v) {}
 +      term_description(const std::string &v1, const std::string &v2,
 +                       bool issym)
 +        : is_matrix_term(true), is_symmetric(issym), var1(v1), var2(v2) {}
++=======
+         : is_matrix_term(false), is_symmetric(false),
+           is_global(false), var1(v) {}
+       term_description(const std::string &v1, const std::string &v2,
+                        bool issym)
+         : is_matrix_term(true), is_symmetric(issym), is_global(false), 
+           var1(v1), var2(v2) {}
+       term_description(bool ism, bool issym)
+         : is_matrix_term(ism), is_symmetric(issym), is_global(true) {}
++>>>>>>> upstream
      };
  
      typedef std::vector<term_description> termlist;
@@@ -227,9 -237,9 +255,13 @@@
                           BUILD_WITH_COMPLETE_RHS = 8,
                           BUILD_COMPLETE_RHS = 9,
                           BUILD_PSEUDO_POTENTIAL = 16
++<<<<<<< HEAD
 +                       };
++=======
+     };
++>>>>>>> upstream
  
-   private :
+   protected:
  
      // rmatlist and cmatlist could be csc_matrix vectors to reduced the
      // amount of memory (but this should add a supplementary copy).
@@@ -247,25 -261,28 +283,43 @@@
        mutable model_real_plain_vector coeffs;
        mutable scalar_type matrix_coeff;
        mutable real_matlist rmatlist;    // Matrices the brick have to fill in
++<<<<<<< HEAD
 +                                        // (real version).
 +      mutable std::vector<real_veclist> rveclist; // Rhs the brick have to
 +                                        // fill in (real version).
++=======
+       // (real version).
+       mutable std::vector<real_veclist> rveclist; // Rhs the brick have to
+       // fill in (real version).
++>>>>>>> upstream
        mutable std::vector<real_veclist> rveclist_sym; // additional rhs for
-                                         //  symmetric terms (real version).
+       //  symmetric terms (real version).
        mutable complex_matlist cmatlist; // Matrices the brick have to fill in
-                                         // (complex version).
+       // (complex version).
        mutable std::vector<complex_veclist> cveclist; // Rhs the brick have to
-                                         // fill in (complex version).
+       // fill in (complex version).
        mutable std::vector<complex_veclist> cveclist_sym;  // additional rhs
++<<<<<<< HEAD
 +                                        // for symmetric terms (real version).
++=======
+       // for symmetric terms (real version).
++>>>>>>> upstream
  
        brick_description(pbrick p, const varnamelist &vl,
                          const varnamelist &dl, const termlist &tl,
                          const mimlist &mms, size_type reg)
          : terms_to_be_computed(true), v_num(0), pbr(p), pdispatch(0), nbrhs(1),
            vlist(vl), dlist(dl), tlist(tl), mims(mms), region(reg),
++<<<<<<< HEAD
 +          rveclist(1), rveclist_sym(1), cveclist(1),
 +          cveclist_sym(1)  { }
++=======
+           partition( (mms.size()>0 ? &mms.at(0)->linked_mesh() : 0),  region),
+           rveclist(1), rveclist_sym(1), cveclist(1),
+           cveclist_sym(1)  { }
+ 
+       brick_description(void) {}      
++>>>>>>> upstream
      };
  
      typedef std::map<std::string, var_description> VAR_SET;
@@@ -277,7 -311,7 +348,11 @@@
      bool check_name_valitity(const std::string &name,
                               bool assert = true) const;
      void brick_init(size_type ib, build_version version,
++<<<<<<< HEAD
 +                      size_type rhs_ind = 0) const;
++=======
+ 		    size_type rhs_ind = 0) const;
++>>>>>>> upstream
  
      void init(void) { complex_version = false; act_size_to_be_done = false; }
  
@@@ -298,14 -332,55 +373,66 @@@
                                   size_type ib) const;
      bool is_var_mf_newer_than_brick(const std::string &varname,
                                      size_type ib) const;
++<<<<<<< HEAD
 +    pbrick get_brick(size_type ib) const IS_DEPRECATED {
 +      GMM_ASSERT1(ib < bricks.size(), "Inexistent brick");
 +      return bricks[ib].pbr;
 +    }
 +    pbrick brick_pointer(size_type ind_brick) const { 
 +      GMM_ASSERT1(ind_brick < bricks.size(), "Inexistent brick");
 +      return bricks[ind_brick].pbr;
 +    }
++=======
+     pbrick brick_pointer(size_type ib) const {
+       GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
+       return bricks[ib].pbr;
+     }
+ 
+     void add_Neumann_term(pNeumann_elem_term p,
+ 			  const std::string &varname,
+ 			  size_type brick_num) const
+     { Neumann_term_list[Neumann_pair(varname, brick_num)] = p; }
+ 
+     size_type check_Neumann_terms_consistency(const std::string &varname)const;
+ 
+     bool check_Neumann_terms_linearity(const std::string &varname) const;
+ 
+     void auxilliary_variables_of_Neumann_terms
+     (const std::string &varname, std::vector<std::string> &aux_var) const;
+ 
+     void add_auxilliary_variables_of_Neumann_terms
+     (const std::string &varname, const std::vector<std::string> &aux_vars) const;
+ 
+     void add_auxilliary_variables_of_Neumann_terms
+     (const std::string &varname, const std::string &aux_var) const;
+ 
+     /* Compute the approximation of the Neumann condition for a variable
+ 	with the declared terms.
+ 	The output tensor has to have the right size. No verification.
+     */
+     void compute_Neumann_terms(int version, const std::string &varname,
+ 			       const mesh_fem &mfvar,    
+ 			       const model_real_plain_vector &var,
+ 			       fem_interpolation_context &ctx,
+ 			       base_small_vector &n,
+ 			       bgeot::base_tensor &output) const;
+ 
+     void compute_auxilliary_Neumann_terms
+     (int version, const std::string &varname,
+      const mesh_fem &mfvar, const model_real_plain_vector &var,
+      const std::string &aux_varname,
+      fem_interpolation_context &ctx, base_small_vector &n,
+      bgeot::base_tensor &output) const;
+ 
+     /* function to be called by Dirichlet bricks */
+     void add_real_dof_constraint(const std::string &varname, size_type dof,
+                             scalar_type val) const
+     { (real_dof_constraints[varname])[dof] = val; }
+     /* function to be called by Dirichlet bricks */
+     void add_complex_dof_constraint(const std::string &varname, size_type dof,
+                                complex_type val) const
+     { (complex_dof_constraints[varname])[dof] = val; }
++>>>>>>> upstream
  
  
      void add_temporaries(const varnamelist &vl, gmm::uint64_type id_num) const;
@@@ -324,6 -399,12 +451,15 @@@
  
      bool temporary_uptodate(const std::string &varname,
                              gmm::uint64_type  id_num, size_type &ind) const;
++<<<<<<< HEAD
++=======
+ 
+     size_type n_iter_of_variable(const std::string &name) const {
+       return (variables.find(name) == variables.end()) ?
+              size_type(0) : variables[name].n_iter;
+     }
+ 
++>>>>>>> upstream
      void set_default_iter_of_variable(const std::string &varname,
                                        size_type ind) const;
      void reset_default_iter_of_variables(const varnamelist &vl) const;
@@@ -338,13 -419,13 +474,22 @@@
  
      /** Disable a brick.  */
      void disable_brick(size_type ib) {
++<<<<<<< HEAD
 +      GMM_ASSERT1(ib < bricks.size(), "Inexistent brick");
 +      active_bricks.sup(ib);
++=======
+       GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
+       active_bricks.del(ib);
++>>>>>>> upstream
      }
  
      /** Enable a brick.  */
      void enable_brick(size_type ib) {
++<<<<<<< HEAD
 +      GMM_ASSERT1(ib < bricks.size(), "Inexistent brick");
++=======
+       GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
++>>>>>>> upstream
        active_bricks.add(ib);
      }
  
@@@ -372,10 -453,7 +517,14 @@@
      /** Total number of degrees of freedom in the model. */
      size_type nb_dof(void) const {
        context_check(); if (act_size_to_be_done) actualize_sizes();
++<<<<<<< HEAD
 +      if (complex_version)
 +        return gmm::vect_size(crhs);
 +      else
 +        return gmm::vect_size(rrhs);
++=======
+       return (complex_version) ? gmm::vect_size(crhs) : gmm::vect_size(rrhs);
++>>>>>>> upstream
      }
  
      /** Leading dimension of the meshes used in the model. */
@@@ -465,12 -551,12 +622,20 @@@
        to_variables(V, T());
      }
  
++<<<<<<< HEAD
 +    /** Add a fixed size variable to the model. niter is the number of version
++=======
+     /** Adds a fixed size variable to the model. niter is the number of version
++>>>>>>> upstream
          of the variable stored, for time integration schemes. */
      void add_fixed_size_variable(const std::string &name, size_type size,
                                   size_type niter = 1);
  
++<<<<<<< HEAD
 +    /** Add a fixed size data to the model. niter is the number of version
++=======
+     /** Adds a fixed size data to the model. niter is the number of version
++>>>>>>> upstream
          of the data stored, for time integration schemes. */
      void add_fixed_size_data(const std::string &name, size_type size,
                               size_type niter = 1);
@@@ -501,25 -587,25 +666,45 @@@
      }
  
  
++<<<<<<< HEAD
 +    /** Add a variable being the dofs of a finite element method to the model.
++=======
+     /** Adds a variable being the dofs of a finite element method to the model.
++>>>>>>> upstream
          niter is the number of version of the variable stored, for time
          integration schemes. */
      void add_fem_variable(const std::string &name, const mesh_fem &mf,
                            size_type niter = 1);
++<<<<<<< HEAD
 +
 +    /** Add a variable linked to a fem with the dof filtered with respect 
 +	to a mesh region. Only the dof returned by the dof_on_region
 +	method of `mf` will be kept. niter is the number of version
 +	of the data stored, for time integration schemes. */
 +    void add_filtered_fem_variable(const std::string &name, const mesh_fem &mf,
 +				   size_type region, size_type niter = 1);
 +
 +    /** Add a data being the dofs of a finite element method to the model.
++=======
+ 
+     /** Adds a variable linked to a fem with the dof filtered with respect 
+ 	to a mesh region. Only the dof returned by the dof_on_region
+ 	method of `mf` will be kept. niter is the number of version
+ 	of the data stored, for time integration schemes. */
+     void add_filtered_fem_variable(const std::string &name, const mesh_fem &mf,
+ 				   size_type region, size_type niter = 1);
+ 
+     /** Adds a data being the dofs of a finite element method to the model.
++>>>>>>> upstream
          The data is initialized with V. */
      void add_fem_data(const std::string &name, const mesh_fem &mf,
                        dim_type qdim = 1, size_type niter = 1);
  
++<<<<<<< HEAD
 +    /** Add a fixed size data to the model. niter is the number of version
++=======
+     /** Adds a fixed size data to the model. niter is the number of version
++>>>>>>> upstream
          of the data stored, for time integration schemes. */
      template <typename VECT>
      void add_initialized_fem_data(const std::string &name, const mesh_fem &mf,
@@@ -532,7 -618,7 +717,11 @@@
          gmm::copy(gmm::real_part(v), this->set_real_variable(name));
      }
  
++<<<<<<< HEAD
 +    /** Add a particular variable linked to a fem being a multiplier with
++=======
+     /** Adds a particular variable linked to a fem being a multiplier with
++>>>>>>> upstream
          respect to a primal variable. The dof will be filtered with the
          gmm::range_basis function applied on the terms of the model which
          link the multiplier and the primal variable. Optimized for boundary
@@@ -542,7 -628,7 +731,11 @@@
                          const std::string &primal_name,
                          size_type niter = 1);
  
++<<<<<<< HEAD
 +    /** Add a particular variable linked to a fem being a multiplier with
++=======
+     /** Adds a particular variable linked to a fem being a multiplier with
++>>>>>>> upstream
          respect to a primal variable. The dof will be filtered with the
          gmm::range_basis function applied on the mass matrix between the fem
  	of the multiplier and the one of the primal variable.
@@@ -552,6 -638,9 +745,12 @@@
                          const std::string &primal_name, const mesh_im &mim,
  			size_type region, size_type niter = 1);
  
++<<<<<<< HEAD
++=======
+     /** Delete a variable or data of the model. */
+     void delete_variable(const std::string &varnamename);
+ 
++>>>>>>> upstream
      /** Gives the access to the mesh_fem of a variable if any. Throw an
          exception otherwise. */
      const mesh_fem &mesh_fem_of_variable(const std::string &name) const;
@@@ -586,7 -675,7 +785,11 @@@
      const model_real_plain_vector &real_brick_term_rhs(size_type ib, size_type ind_term = 0, bool sym = false, size_type ind_iter = 0) const {
        GMM_ASSERT1(!complex_version, "This model is a complex one");
        context_check(); if (act_size_to_be_done) actualize_sizes();
++<<<<<<< HEAD
 +      GMM_ASSERT1(ib < bricks.size(), "Inexistent brick");
++=======
+       GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
++>>>>>>> upstream
        GMM_ASSERT1(ind_term < bricks[ib].tlist.size(), "Inexistent term");
        GMM_ASSERT1(ind_iter < bricks[ib].nbrhs, "Inexistent iter");
        GMM_ASSERT1(!sym || bricks[ib].tlist[ind_term].is_symmetric,
@@@ -616,7 -705,7 +819,11 @@@
      const model_complex_plain_vector &complex_brick_term_rhs(size_type ib, size_type ind_term = 0, bool sym = false, size_type ind_iter = 0) const {
        GMM_ASSERT1(!complex_version, "This model is a complex one");
        context_check(); if (act_size_to_be_done) actualize_sizes();
++<<<<<<< HEAD
 +      GMM_ASSERT1(ib < bricks.size(), "Inexistent brick");
++=======
+       GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
++>>>>>>> upstream
        GMM_ASSERT1(ind_term < bricks[ib].tlist.size(), "Inexistent term");
        GMM_ASSERT1(ind_iter < bricks[ib].nbrhs, "Inexistent iter");
        GMM_ASSERT1(!sym || bricks[ib].tlist[ind_term].is_symmetric,
@@@ -635,32 -724,35 +842,61 @@@
      void listbricks(std::ostream &ost, size_type base_id = 0) const;
  
      /** Force the re-computation of a brick for the next assembly. */
++<<<<<<< HEAD
 +    void touch_brick(size_type ind_brick) {
 +      GMM_ASSERT1(ind_brick < bricks.size(), "Inexistent brick");
 +      bricks[ind_brick].terms_to_be_computed = true;
 +    }
 +
 +    /** Add a brick to the model. varname is the list of variable used
 +        and datanames the data used. If a variable is used as a data, it
 +        should be declared in the datanames (it will depend on the value of
 +        the variable not only on the fem). */
++=======
+     void touch_brick(size_type ib) {
+       GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
+       bricks[ib].terms_to_be_computed = true;
+     }
+ 
+     /** Adds a brick to the model. varname is the list of variable used
+         and datanames the data used. If a variable is used as a data, it
+         should be declared in the datanames (it will depend on the value of
+         the variable not only on the fem). Returns the brick index. */
++>>>>>>> upstream
      size_type add_brick(pbrick pbr, const varnamelist &varnames,
                          const varnamelist &datanames,
                          const termlist &terms, const mimlist &mims,
                          size_type region);
++<<<<<<< HEAD
 +    
 +    /** Add an integration method to a brick. */
 +    void add_mim_to_brick(size_type ib, const mesh_im &mim);
 +
 +    /** Change the term list of a brick. Used for very special bricks only. */
 +    void change_terms_of_brick(size_type ib, const termlist &terms);
 +
 +    /** Change the variable list of a brick. Used for very special bricks only.
 +     */
 +    void change_variables_of_brick(size_type ib, const varnamelist &vl);
 +
++=======
++>>>>>>> upstream
+ 
+     /** Delete the brick of index ib from the model. */
+     void delete_brick(size_type ib);
+     
+     /** Adds an integration method to a brick. */
+     void add_mim_to_brick(size_type ib, const mesh_im &mim);
+ 
+     /** Change the term list of a brick. Used for very special bricks only. */
+     void change_terms_of_brick(size_type ib, const termlist &terms);
+ 
+     /** Change the variable list of a brick. Used for very special bricks only.
+      */
+     void change_variables_of_brick(size_type ib, const varnamelist &vl);
+ 
  
-     /** Add a time dispacther to a brick. */
+     /** Adds a time dispacther to a brick. */
      void add_time_dispatcher(size_type ibrick, pdispatcher pdispatch);
  
      void set_dispatch_coeff(void);
@@@ -702,10 -799,10 +943,17 @@@
        leading_dim = 0;
      }
  
++<<<<<<< HEAD
 +	/**check consistency of RHS and Stiffness matrix for brick with 
 +	* @param  ind_brick  - index of the brick
 +	*/
 +	void check_brick_stiffness_rhs(size_type ind_brick) const;
++=======
+     /**check consistency of RHS and Stiffness matrix for brick with 
+      * @param  ind_brick  - index of the brick
+      */
+     void check_brick_stiffness_rhs(size_type ind_brick) const;
++>>>>>>> upstream
  
  
    };
@@@ -856,7 -953,8 +1104,12 @@@
      bool iscomplex;   // The brick admits a complex version or not.
      bool isinit;      // internal flag.
      bool compute_each_time; // The brick is linear but needs to be computed
++<<<<<<< HEAD
 +                            // each time it is evaluated.
++=======
+     // each time it is evaluated.
+     bool hasNeumannterm; // The brick declares at list a Neumann term.
++>>>>>>> upstream
      std::string name; // Name of the brick.
  
    public :
@@@ -865,11 -963,12 +1118,20 @@@
  
      virtual_brick(void) { isinit = false; }
      void set_flags(const std::string &bname, bool islin, bool issym,
++<<<<<<< HEAD
 +                   bool iscoer, bool ire, bool isco, bool each_time = false) {
 +      name = bname;
 +      islinear = islin; issymmetric = issym; iscoercive = iscoer;
 +      isreal = ire; iscomplex = isco; isinit = true;
 +      compute_each_time = each_time;
++=======
+                    bool iscoer, bool ire, bool isco, bool each_time = false,
+ 		   bool hasNeumannt = true) {
+       name = bname;
+       islinear = islin; issymmetric = issym; iscoercive = iscoer;
+       isreal = ire; iscomplex = isco; isinit = true;
+       compute_each_time = each_time; hasNeumannterm = hasNeumannt;
++>>>>>>> upstream
      }
  
  #   define BRICK_NOT_INIT GMM_ASSERT1(isinit, "Set brick flags !")
@@@ -878,6 -977,7 +1140,10 @@@
      bool is_coercive(void)  const { BRICK_NOT_INIT; return iscoercive;  }
      bool is_real(void)      const { BRICK_NOT_INIT; return isreal;      }
      bool is_complex(void)   const { BRICK_NOT_INIT; return iscomplex;   }
++<<<<<<< HEAD
++=======
+     bool has_Neumann_term(void) const { BRICK_NOT_INIT;return hasNeumannterm; }
++>>>>>>> upstream
      bool is_to_be_computed_each_time(void) const
      { BRICK_NOT_INIT; return compute_each_time; }
      const std::string &brick_name(void) const { BRICK_NOT_INIT; return name; }
@@@ -929,23 -1029,60 +1195,75 @@@
        return scalar_type(0);
      }
  
++<<<<<<< HEAD
 +	/**check consistency of stiffness matrix and rhs*/
 +	void check_stiffness_matrix_and_rhs(const model &, size_type,
++=======
+     /**check consistency of stiffness matrix and rhs*/
+     void check_stiffness_matrix_and_rhs(const model &, size_type,
+                                         const model::termlist& tlist,
++>>>>>>> upstream
                                          const model::varnamelist &,
                                          const model::varnamelist &,
                                          const model::mimlist &,
                                          model::real_matlist &,
                                          model::real_veclist &,
                                          model::real_veclist &, size_type rg,
++<<<<<<< HEAD
 +										const scalar_type delta = 1e-8) const;
 +
 +
 +
++=======
+ 					const scalar_type delta = 1e-8) const;
  
    };
  
+   //=========================================================================
+   //
+   //  Neumann term object.
+   //
+   //=========================================================================
+ 
+   /* For a PDE in a weak form, the Neumann condition correspond to
+      prescribe a certain derivative of the unkown (the normal derivative
+      for the Poisson problem for instance). The Neumann term objects allows
+      to compute the finite element approximation of this certain derivative.
+      This allows, first ot have an estimate of this term (for instance, it can
+      give an approximation of the stress at the boundary in a problem of
+      linear elasticity) but also it allows to prescribe some boundary
+      conditions with Nitsche's method (For dirichlet or contact boundary
+      conditions for instance).
+   */
+ 
+   struct Neumann_elem_term : virtual public dal::static_stored_object {
+ 
+     std::vector<std::string> auxilliary_variables;
+ 
+     // The function should return the Neumann term when version = 1,
+     // its derivative when version = 2 and its second derivative
+     // when version = 3.
+     // CAUTION : The output tensor has the right size and the reult has to
+     //           be ADDED. previous additions of other term have not to be
+     //           erased.
  
+     virtual void compute_Neumann_term
+     (int version, const mesh_fem &/*mfvar*/,
+      const model_real_plain_vector &/*var*/,
+      fem_interpolation_context& /*ctx*/,
+      base_small_vector &/*n*/, base_tensor &/*output*/,
+      size_type /*auxilliary_ind*/ = 0) const = 0;
++>>>>>>> upstream
  
+   };
+ 
+ 
+ 
++<<<<<<< HEAD
++=======
+ 
+ 
++>>>>>>> upstream
    //=========================================================================
    //
    //  Functions adding standard bricks to the model.
@@@ -953,7 -1090,7 +1271,11 @@@
    //=========================================================================
  
  
++<<<<<<< HEAD
 +  /** Add a Laplacian term on the variable `varname` (in fact with a minus :
++=======
+   /** Adds a Laplacian term on the variable `varname` (in fact with a minus :
++>>>>>>> upstream
        :math:`-\text{div}(\nabla u)`). If it is a vector
        valued variable, the Laplacian term is componentwise. `region` is an
        optional mesh region on which the term is added. Return the brick index
@@@ -962,9 -1099,9 +1284,13 @@@
    size_type add_Laplacian_brick
    (model &md, const mesh_im &mim, const std::string &varname,
     size_type region = size_type(-1));
++<<<<<<< HEAD
++
++=======
++>>>>>>> upstream
  
  
-   /** Add an elliptic term on the variable `varname`. The shape of the elliptic
+   /** Adds an elliptic term on the variable `varname`. The shape of the elliptic
        term depends both on the variable and the data. This corresponds to a
        term $-\text{div}(a\nabla u)$ where $a$ is the data and $u$ the variable.
        The data can be a scalar, a matrix or an order four tensor. The variable
@@@ -983,9 -1120,9 +1309,13 @@@
    size_type add_generic_elliptic_brick
    (model &md, const mesh_im &mim, const std::string &varname,
     const std::string &dataname, size_type region = size_type(-1));
++<<<<<<< HEAD
 +
++=======
++>>>>>>> upstream
  
-   /** Add a source term on the variable `varname`. The source term is
+ 
+   /** Adds a source term on the variable `varname`. The source term is
        represented by the data `dataname` which could be constant or described
        on a fem.  `region` is an optional mesh region on which the term is
        added. An additional optional data `directdataname` can be provided. The
@@@ -1068,8 -1230,32 +1423,37 @@@
     const std::string &dataname = std::string(),
     const mesh_fem *mf_mult = 0);
  
++<<<<<<< HEAD
 +  /** Add a Dirichlet condition to the normal component of the vector
 +     (or tensor) valued variable `varname` and the mesh
++=======
+   /** Adds a Dirichlet condition on the variable `varname` and the mesh
+       region `region`. This region should be a boundary. The Dirichlet
+       condition is prescribed with Nitsche's method. `dataname` is the optional
+       right hand side of the Dirichlet condition. It could be constant or
+       described on a fem; scalar or vector valued, depending on the variable
+       on which the Dirichlet condition is prescribed. `gamma0name` is the
+       Nitsche's method parameter. `theta` is a scalar value which can be
+       positive or negative. `theta = 1` corresponds to the standard symmetric
+       method which is conditionnaly coercive for  `gamma0` small.
+       `theta = -1` corresponds to the skew-symmetric method which is
+       inconditionnaly coercive. `theta = 0` is the simplest method
+       for which the second derivative of the Neumann term is not necessary
+       even for nonlinear problems. Returns the brick index in the model.
+       CAUTION: This brick has to be added in the model after all the bricks
+       corresponding to partial differential terms having a Neumann term.
+       Moreover, This brick can only be applied to bricks declaring their
+       Neumann terms.
+   */
+   size_type add_Dirichlet_condition_with_Nitsche_method
+   (model &md, const mesh_im &mim, const std::string &varname,
+    const std::string &gamma0name, size_type region,
+    scalar_type theta = scalar_type(1),
+    const std::string &dataname = std::string());
+ 
+   /** Adds a Dirichlet condition to the normal component of the vector
+       (or tensor) valued variable `varname` and the mesh
++>>>>>>> upstream
        region `region`. This region should be a boundary. The Dirichlet
        condition is prescribed with a multiplier variable `multname` which
        should be first declared as a multiplier
@@@ -1100,14 -1286,14 +1484,23 @@@
    /** Same function as the previous one but the `mf_mult` parameter is
        replaced by `degree`. The multiplier will be described on a standard
        finite element method of the corresponding degree.
++<<<<<<< HEAD
 +   */
++=======
+   */
++>>>>>>> upstream
    size_type add_normal_Dirichlet_condition_with_multipliers
    (model &md, const mesh_im &mim, const std::string &varname,
     dim_type degree, size_type region,
     const std::string &dataname = std::string());
  
++<<<<<<< HEAD
 +  /** Add a Dirichlet condition to the normal component of the vector
 +     (or tensor) valued variable `varname` and the mesh
++=======
+   /** Adds a Dirichlet condition to the normal component of the vector
+       (or tensor) valued variable `varname` and the mesh
++>>>>>>> upstream
        region `region`. This region should be a boundary. The Dirichlet
        condition is prescribed with penalization. The penalization coefficient
        is intially `penalization_coeff` and will be added to the data of
@@@ -1127,7 -1313,33 +1520,37 @@@
     const mesh_fem *mf_mult = 0);
  
  
++<<<<<<< HEAD
 +  /** Add some pointwise constraints on the variable `varname` thanks to
++=======
+   /** Adds a Dirichlet condition to the normal component of the vector
+       (or tensor) valued variable `varname` and the mesh region `region`.
+       This region should be a boundary. The Dirichlet
+       condition is prescribed with Nitsche's method. `dataname` is the optional
+       right hand side of the Dirichlet condition. It could be constant or
+       described on a fem. `gamma0name` is the
+       Nitsche's method parameter. `theta` is a scalar value which can be
+       positive or negative. `theta = 1` corresponds to the standard symmetric
+       method which is conditionnaly coercive for  `gamma0` small.
+       `theta = -1` corresponds to the skew-symmetric method which is
+       inconditionnaly coercive. `theta = 0` is the simplest method
+       for which the second derivative of the Neumann term is not necessary
+       even for nonlinear problems. Returns the brick index in the model.
+       CAUTION: This brick has to be added in the model after all the bricks
+       corresponding to partial differential terms having a Neumann term.
+       Moreover, This brick can only be applied to bricks declaring their
+       Neumann terms. 
+       (This brick is not fully tested)
+   */
+   size_type add_normal_Dirichlet_condition_with_Nitsche_method
+   (model &md, const mesh_im &mim, const std::string &varname,
+    const std::string &gamma0name, size_type region,
+    scalar_type theta = scalar_type(1),
+    const std::string &dataname = std::string());
+ 
+ 
+   /** Adds some pointwise constraints on the variable `varname` thanks to
++>>>>>>> upstream
        a penalization. The penalization coefficient is initially
        `penalization_coeff` and will be added to the data of the model.
        The conditions are prescribed on a set of points given in the data
@@@ -1150,7 -1362,7 +1573,11 @@@
     const std::string &dataname_val = std::string());
  
  
++<<<<<<< HEAD
 +  /** Add some pointwise constraints on the variable `varname` using a given
++=======
+   /** Adds some pointwise constraints on the variable `varname` using a given
++>>>>>>> upstream
        multiplier `multname`.
        The conditions are prescribed on a set of points given in the data
        `dataname_pt` whose dimension is the number of points times the dimension
@@@ -1174,7 -1386,7 +1601,11 @@@
     const std::string &dataname_unitv = std::string(),
     const std::string &dataname_val = std::string());
  
++<<<<<<< HEAD
 +  /** Add some pointwise constraints on the variable `varname` using
++=======
+   /** Adds some pointwise constraints on the variable `varname` using
++>>>>>>> upstream
        multiplier. The multiplier variable is automatically added to the model.
        The conditions are prescribed on a set of points given in the data
        `dataname_pt` whose dimension is the number of points times the dimension
@@@ -1293,7 -1534,7 +1753,11 @@@
                                      size_type region);
  
  
++<<<<<<< HEAD
 +  /** Add a brick representing a scalar term (@f$f(u)@f$) to the left-hand
++=======
+   /** Adds a brick representing a scalar term (@f$f(u)@f$) to the left-hand
++>>>>>>> upstream
        side of the model. In the weak form, one adds (@f$ +\int f(u)v at f$). The
        function $f$ may optionally depend on $\lambda$, i.e.,
        $f(u) = f(u, \lambda)$.
@@@ -1303,7 -1544,7 +1767,11 @@@
        optional mesh region on which the term is added. `dataname` represents
        the optional real scalar parameter $\lambda$ in the model. Return the
        brick index in the model.
++<<<<<<< HEAD
 +   */
++=======
+   */
++>>>>>>> upstream
    size_type add_basic_nonlinear_brick
    (model &md, const mesh_im &mim, const std::string &varname,
     const std::string &f, const std::string &dfdu,
@@@ -1326,7 -1567,7 +1794,11 @@@
  
    template <typename VECT, typename T>
    void set_private_data_rhs(model &md, size_type ind,
++<<<<<<< HEAD
 +                                const VECT &L, T) {
++=======
+ 			    const VECT &L, T) {
++>>>>>>> upstream
      model_real_plain_vector &LL = set_private_data_brick_real_rhs(md, ind);
      gmm::resize(LL, gmm::vect_size(L));
      gmm::copy(L, LL);
@@@ -1334,7 -1575,7 +1806,11 @@@
  
    template <typename VECT, typename T>
    void set_private_data_rhs(model &md, size_type ind, const VECT &L,
++<<<<<<< HEAD
 +                           std::complex<T>) {
++=======
+ 			    std::complex<T>) {
++>>>>>>> upstream
      model_complex_plain_vector &LL=set_private_data_brick_complex_rhs(md, ind);
      gmm::resize(LL, gmm::vect_size(L));
      gmm::copy(L, LL);
@@@ -1352,7 -1593,7 +1828,11 @@@
  
    template <typename MAT, typename T>
    void set_private_data_matrix(model &md, size_type ind,
++<<<<<<< HEAD
 +                                   const MAT &B, T) {
++=======
+ 			       const MAT &B, T) {
++>>>>>>> upstream
      model_real_sparse_matrix &BB = set_private_data_brick_real_matrix(md, ind);
      gmm::resize(BB, gmm::mat_nrows(B), gmm::mat_ncols(B));
      gmm::copy(B, BB);
@@@ -1360,7 -1601,7 +1840,11 @@@
  
    template <typename MAT, typename T>
    void set_private_data_matrix(model &md, size_type ind, const MAT &B,
++<<<<<<< HEAD
 +                              std::complex<T>) {
++=======
+ 			       std::complex<T>) {
++>>>>>>> upstream
      model_complex_sparse_matrix &BB
        = set_private_data_brick_complex_matrix(md, ind);
      gmm::resize(BB, gmm::mat_nrows(B), gmm::mat_ncols(B));
@@@ -1372,7 -1613,7 +1856,11 @@@
        set this matrix. @*/
    template <typename MAT>
    void set_private_data_matrix(model &md, size_type indbrick,
++<<<<<<< HEAD
 +                                   const MAT &B) {
++=======
+ 			       const MAT &B) {
++>>>>>>> upstream
      typedef typename gmm::linalg_traits<MAT>::value_type T;
      set_private_data_matrix(md, indbrick, B, T());
    }
@@@ -1420,7 -1661,7 +1908,11 @@@
                                  bool issymmetric, bool iscoercive);
    size_type add_explicit_rhs(model &md, const std::string &varname);
  
++<<<<<<< HEAD
 +  /** Add a brick reprenting an explicit matrix to be added to the tangent
++=======
+   /** Adds a brick reprenting an explicit matrix to be added to the tangent
++>>>>>>> upstream
        linear system relatively to the variables 'varname1' and 'varname2'.
        The given matrix should have as many rows as the dimension of
        'varname1' and as many columns as the dimension of 'varname2'.
diff --cc src/getfem/getfem_nonlinear_elasticity.h
index 157ec16,910e25e..50bc2ff
--- a/src/getfem/getfem_nonlinear_elasticity.h
+++ b/src/getfem/getfem_nonlinear_elasticity.h
@@@ -150,31 -156,31 +156,58 @@@ namespace getfem 
  		       const base_vector &params, scalar_type det_trans) const;
      virtual void grad_sigma(const base_matrix &E, base_tensor &result,
  			    const base_vector &params, scalar_type det_trans) const;
++<<<<<<< HEAD
 +    Mooney_Rivlin_hyperelastic_law(void);
++=======
+     Mooney_Rivlin_hyperelastic_law(bool compressible_=false,
+                                    bool neohookean_=false);
++>>>>>>> upstream
    };
  
  
    /** Blatz_Ko hyperelastic law 
++<<<<<<< HEAD
 +      
 +      To be used for compressible problems.
 +  */
 +  struct generalized_Blatz_Ko_hyperelastic_law : public abstract_hyperelastic_law {
 +    virtual scalar_type strain_energy(const base_matrix &E,
 +				      const base_vector &params, scalar_type det_trans) const;
 +    virtual void sigma(const base_matrix &E, base_matrix &result,
 +		       const base_vector &params, scalar_type det_trans) const;
 +    virtual void grad_sigma(const base_matrix &E, base_tensor &result,
 +			    const base_vector &params, scalar_type det_trans) const;
 +    generalized_Blatz_Ko_hyperelastic_law(void);
 +  };
 +
 +
 +  /** Ciarlet-Geymonat hyperelastic law ( @f$ W=~_1i_1(L) + \frac{~}{2}i_2(L) + 8ci_3(L) - \frac{~_1}{2} \textrm{log}~\textrm{det}~C @f$ )
++=======
++>>>>>>> upstream
        
+       To be used for compressible problems.
+   */
+   struct generalized_Blatz_Ko_hyperelastic_law : public abstract_hyperelastic_law {
+     virtual scalar_type strain_energy(const base_matrix &E,
+ 				      const base_vector &params, scalar_type det_trans) const;
+     virtual void sigma(const base_matrix &E, base_matrix &result,
+ 		       const base_vector &params, scalar_type det_trans) const;
+     virtual void grad_sigma(const base_matrix &E, base_tensor &result,
+ 			    const base_vector &params, scalar_type det_trans) const;
+     generalized_Blatz_Ko_hyperelastic_law(void);
+   };
+ 
+ 
+   /** Ciarlet-Geymonat hyperelastic law
     */
    struct Ciarlet_Geymonat_hyperelastic_law : public abstract_hyperelastic_law {
++<<<<<<< HEAD
 +    // parameters are lambda=params[0], mu=params[1], gamma'(1)=params[2]
 +    // The parameter gamma'(1) has to verify gamma'(1) in ]max{-lambda/2-mu, -2mu}, -mu[
++=======
+     // parameters are lambda=params[0], mu=params[1], a=params[2]
+     // The parameter a has to verify a in ]0, mu/2[
++>>>>>>> upstream
      virtual scalar_type strain_energy(const base_matrix &E,
  				      const base_vector &params, scalar_type det_trans) const;
      virtual void sigma(const base_matrix &E, base_matrix &result,
diff --cc src/getfem/getfem_plasticity.h
index d2a91ad,6b36d3d..77cedde
--- a/src/getfem/getfem_plasticity.h
+++ b/src/getfem/getfem_plasticity.h
@@@ -1,10 -1,10 +1,18 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2002-2012 Amandine Cottaz, Yves Renard
 + 
 + This file is a part of GETFEM++
 + 
++=======
+ 
+  Copyright (C) 2002-2012 Amandine Cottaz, Yves Renard
+ 
+  This file is a part of GETFEM++
+ 
++>>>>>>> upstream
   Getfem++  is  free software;  you  can  redistribute  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
@@@ -17,7 -17,7 +25,11 @@@
   You  should  have received a copy of the GNU Lesser General Public License
   along  with  this program;  if not, write to the Free Software Foundation,
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
   As a special exception, you  may use  this file  as it is a part of a free
   software  library  without  restriction.  Specifically,  if   other  files
   instantiate  templates  or  use macros or inline functions from this file,
@@@ -26,7 -26,7 +38,11 @@@
   to be covered  by the GNU Lesser General Public License.  This   exception
   does not  however  invalidate  any  other  reasons why the executable file
   might be covered by the GNU Lesser General Public License.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  /**@file getfem_plasticity.h
diff --cc src/getfem/getfem_projected_fem.h
index 2b63a05,4e131b2..9f12379
--- a/src/getfem/getfem_projected_fem.h
+++ b/src/getfem/getfem_projected_fem.h
@@@ -134,6 -134,8 +134,11 @@@ namespace getfem 
  
      void projection_data(const fem_interpolation_context& c,
                           base_node &normal, scalar_type &gap) const;
++<<<<<<< HEAD
++=======
+     void projection_data(const base_node &pt,
+                          base_node &normal, scalar_type &gap) const;
++>>>>>>> upstream
  
      /** return the list of convexes of the projected mesh_fem which
       *  contain at least one gauss point (should be all convexes)! */
@@@ -149,7 -151,7 +154,11 @@@
      projected_fem(const mesh_fem &mf_source_, const mesh_im &mim_target_,
                    size_type rg_source_, size_type rg_target_,
                    dal::bit_vector blocked_dofs_,
++<<<<<<< HEAD
 +                  bool store_val = true);
++=======
+                   bool store_val);
++>>>>>>> upstream
  
      friend pfem new_projected_fem(const mesh_fem &mf_source_,
                                    const mesh_im &mim_target_,
diff --cc src/getfem_contact_and_friction_integral.cc
index 859d420,fb4b176..a70c143
--- a/src/getfem_contact_and_friction_integral.cc
+++ b/src/getfem_contact_and_friction_integral.cc
@@@ -1,9 -1,10 +1,19 @@@
++<<<<<<< HEAD
 +/*===========================================================================
 + 
 + Copyright (C) 2011-2012 Yves Renard, Konstantinos Poulios.
 + 
 + This file is a part of GETFEM++
 + 
++=======
+ /* -*- c++ -*- (enables emacs c++ mode) */
+ /*===========================================================================
+ 
+  Copyright (C) 2011-2013 Yves Renard, Konstantinos Poulios.
+ 
+  This file is a part of GETFEM++
+ 
++>>>>>>> upstream
   Getfem++  is  free software;  you  can  redistribute  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
@@@ -16,13 -17,14 +26,21 @@@
   You  should  have received a copy of the GNU Lesser General Public License
   along  with  this program;  if not, write to the Free Software Foundation,
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  #include "getfem/bgeot_rtree.h"
  #include "getfem/getfem_contact_and_friction_integral.h"
  #include "getfem/getfem_contact_and_friction_common.h"
  #include "getfem/getfem_projected_fem.h"
++<<<<<<< HEAD
++=======
+ #include "gmm/gmm_condition_number.h"
++>>>>>>> upstream
  
  #include <getfem/getfem_arch_config.h>
  #if GETFEM_HAVE_MUPARSER_MUPARSER_H
@@@ -54,7 -56,7 +72,11 @@@ namespace getfem 
      case RHS_U_FRICT_V8: case RHS_U_FRICT_V1:
      case RHS_U_FRICT_V4: case RHS_U_FRICT_V5:
      case RHS_L_FRICT_V1: case RHS_L_FRICT_V2: case RHS_L_FRICT_V4:
++<<<<<<< HEAD
 +    case K_UL_V1:        case K_UL_V2:        case K_UL_V3:  case K_UL_V4:
++=======
+     case K_UL_V1:        case K_UL_V2:        case K_UL_V3:
++>>>>>>> upstream
      case UZAWA_PROJ_FRICT: case UZAWA_PROJ_FRICT_SAXCE:
        sizes_[0] = N; break;
        // two-dimensional tensors [N x N]
@@@ -74,12 -76,36 +96,44 @@@
      gmm::resize(GP, N, N);
    }
  
++<<<<<<< HEAD
++=======
+   void contact_nonlinear_term::friction_law
+   (scalar_type p, scalar_type &tau) {
+     tau = (p > scalar_type(0)) ? tau_adh + f_coeff * p : scalar_type(0);
+     if (tau > tresca_lim) tau = tresca_lim;
+   }
+ 
+   void contact_nonlinear_term::friction_law
+   (scalar_type p, scalar_type &tau, scalar_type &tau_grad) {
+     if (p <= scalar_type(0)) {
+       tau = scalar_type(0);
+       tau_grad = scalar_type(0);
+     }
+     else {
+       tau = tau_adh + f_coeff * p;
+       if (tau > tresca_lim) {
+         tau = tresca_lim;
+         tau_grad = scalar_type(0);
+       }
+       else
+         tau_grad = f_coeff;
+     }
+   }
+ 
++>>>>>>> upstream
    void contact_nonlinear_term::compute
    (fem_interpolation_context &/* ctx */, bgeot::base_tensor &t) {
  
      t.adjust_sizes(sizes_);
++<<<<<<< HEAD
 +    scalar_type e, f, augm_ln;
 +    dim_type i, j;
++=======
+     scalar_type e, augm_ln, rho, rho_grad;
+     dim_type i, j;
+     bool coulomb;
++>>>>>>> upstream
  
      switch (option) {
  
@@@ -99,10 -125,11 +153,18 @@@
        t[0] = -gmm::neg(ln - r*(un - g)); break;
  
      case CONTACT_FLAG:
++<<<<<<< HEAD
 +      // here ln is expected to be an estimation of the mesh size
 +      // and r should be a threshold coefficient expressing a penetration
 +      // or separation distance as percentage of the mesh size 
 +      t[0] = Heav(un-g - r*ln);  break;
++=======
+       // here ln is expected to be a threshold value expressing a penetration
+       // (positive value) or separation (negative value) distance
+       t[0] = Heav(un-g - ln);  break;
+     case CONTACT_PRESSURE:
+       t[0] = -ln;  break;
++>>>>>>> upstream
  
      // one-dimensional tensors [N]
  
@@@ -122,15 -149,17 +184,29 @@@
        break;
      case RHS_U_FRICT_V6:
        e = gmm::neg(ln-r*(un - g));
++<<<<<<< HEAD
 +      auxN = lt - zt;  ball_projection(auxN, f_coeff*e );
 +      for (i=0; i<N; ++i) t[i] = (auxN[i] - e*no[i]);
 +      break;
 +    case RHS_U_FRICT_V7:
 +      e = - gmm::neg(-r*(un - g));
 +      auxN = - zt;  ball_projection(auxN, -f_coeff *e );
 +      for (i=0; i<N; ++i) t[i] = (e*no[i] + auxN[i]);
 +      break;
 +    case RHS_U_FRICT_V8:
++=======
+       friction_law(e, rho);
+       auxN = lt - zt;  ball_projection(auxN, rho);
+       for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
+       break;
+     case RHS_U_FRICT_V7:
+       e = gmm::neg(-r*(un - g));
+       friction_law(e, rho);
+       auxN = - zt;  ball_projection(auxN, rho);
+       for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
+       break;
+     case RHS_U_FRICT_V8: // ignores friction_law, assumes pure Coulomb friction
++>>>>>>> upstream
        auxN = lnt - (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no - zt;
        De_Saxce_projection(auxN, no, f_coeff);
        for (i=0; i<N; ++i) t[i] = auxN[i];
@@@ -138,29 -167,32 +214,55 @@@
      case RHS_U_FRICT_V1:
        for (i=0; i<N; ++i) t[i] = lnt[i]; break;
      case RHS_U_FRICT_V4:
++<<<<<<< HEAD
 +      e = -gmm::neg(ln);
 +      // if (e < 0. && ctx.xreal()[1] > 1.)
 +      //        cout << "x = " << ctx.xreal() << " e = " << e << endl;
 +      auxN = lt;  ball_projection(auxN, f_coeff * gmm::neg(ln));
 +      // if (gmm::vect_norm2(auxN) > 0. && ctx.xreal()[1] > 1.)
 +      //        cout << "x = " << ctx.xreal() << " auxN = " << auxN << endl;
 +      for (i=0; i<N; ++i) t[i] = no[i]*e + auxN[i];
 +      break;
 +    case RHS_U_FRICT_V5:
++=======
+       e = gmm::neg(ln);
+       // if (e > 0. && ctx.xreal()[1] > 1.)
+       //        cout << "x = " << ctx.xreal() << " e = " << e << endl;
+       friction_law(e, rho);
+       auxN = lt;  ball_projection(auxN, rho);
+       // if (gmm::vect_norm2(auxN) > 0. && ctx.xreal()[1] > 1.)
+       //        cout << "x = " << ctx.xreal() << " auxN = " << auxN << endl;
+       for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
+       break;
+     case RHS_U_FRICT_V5: // ignores friction_law, assumes pure Coulomb friction
++>>>>>>> upstream
        auxN = lnt; De_Saxce_projection(auxN, no, f_coeff);
        for (i=0; i<N; ++i) t[i] = auxN[i];
        break;
      case RHS_L_FRICT_V1:
        e = gmm::neg(ln-r*(un-g));
++<<<<<<< HEAD
 +      auxN = zt - lt;  ball_projection(auxN, f_coeff * e); auxN += lt;
++=======
+       friction_law(e, rho);
+       auxN = zt - lt;  ball_projection(auxN, rho); auxN += lt;
++>>>>>>> upstream
        for (i=0; i<N; ++i) t[i] = ((e+ln)*no[i] + auxN[i])/ r;
        break;
      case RHS_L_FRICT_V2:
        e = r*(un-g) + gmm::pos(ln);
++<<<<<<< HEAD
 +      auxN = lt;  ball_projection(auxN, f_coeff * gmm::neg(ln));
 +      for (i=0; i<N; ++i) t[i] = (no[i]*e + zt[i] + lt[i] - auxN[i])/r;
 +      break;
 +    case RHS_L_FRICT_V4:
++=======
+       friction_law(gmm::neg(ln), rho);
+       auxN = lt;  ball_projection(auxN, rho);
+       for (i=0; i<N; ++i) t[i] = (no[i]*e + zt[i] + lt[i] - auxN[i])/r;
+       break;
+     case RHS_L_FRICT_V4: // ignores friction_law, assumes pure Coulomb friction
++>>>>>>> upstream
        auxN = lnt;
        De_Saxce_projection(auxN, no, f_coeff);
        auxN -= lnt + (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no + zt;
@@@ -177,15 -209,13 +279,25 @@@
        e = -Heav(r*(un-g)-ln);
        for (i=0; i<N; ++i) t[i] = e*no[i];
        break;
++<<<<<<< HEAD
 +    case K_UL_V4:
 +      for (i=0; i<N; ++i) t[i] = -no[i];
 +      break;
 +    case UZAWA_PROJ_FRICT:
 +      e = -gmm::neg(ln - r*(un - g));
 +      auxN = lt - zt;  ball_projection(auxN, -f_coeff * e);
 +      for (i=0; i<N; ++i) t[i] = e*no[i] + auxN[i];
 +      break;
 +    case UZAWA_PROJ_FRICT_SAXCE:
++=======
+     case UZAWA_PROJ_FRICT:
+       e = gmm::neg(ln - r*(un - g));
+       friction_law(e, rho);
+       auxN = lt - zt;  ball_projection(auxN, rho);
+       for (i=0; i<N; ++i) t[i] = auxN[i] - e*no[i];
+       break;
+     case UZAWA_PROJ_FRICT_SAXCE: // ignores friction_law, assumes pure Coulomb friction
++>>>>>>> upstream
        auxN = lnt - (r*(un-g) - f_coeff * gmm::vect_norm2(zt)) * no - zt;
        De_Saxce_projection(auxN, no, f_coeff);
        for (i=0; i<N; ++i) t[i] = auxN[i];
@@@ -194,11 -224,11 +306,19 @@@
      // two-dimensional tensors [N x N]
  
      case K_UU_V1:
++<<<<<<< HEAD
 +      e = Heav(un - g) * r;
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j) t[i*N+j] = e * no[i] * no[j];
 +      break;
 +    case K_UU_V2:
 +      e = r*Heav(r*(un - g)-ln);
++=======
+       e = r * Heav(un - g);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j) t[i*N+j] = e * no[i] * no[j];
+       break;
+     case K_UU_V2:
+       e = r * Heav(r*(un - g)-ln);
++>>>>>>> upstream
        for (i=0; i<N; ++i) for (j=0; j<N; ++j) t[i*N+j] = e * no[i] * no[j];
        break;
  
@@@ -207,41 -237,49 +327,87 @@@
          t[i*N+j] = ((i == j) ? -scalar_type(1) : scalar_type(0));
        break;
      case K_UL_FRICT_V2:
++<<<<<<< HEAD
 +      e = -Heav(-ln); //Heav(ln)-scalar_type(1);
 +      ball_projection_grad(lt, f_coeff * gmm::neg(ln), GP);
 +       e += gmm::vect_sp(GP, no, no);
 +      ball_projection_grad_r(lt, f_coeff * gmm::neg(ln), V);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = no[i]*no[j]*e - GP(i,j) + f_coeff*Heav(-ln)*no[i]*V[j];
 +      break;
 +    case K_UL_FRICT_V3:
 +      f = Heav(r*(un-g)-ln);
 +      augm_ln = gmm::neg(ln - r*(un-g));
 +      auxN = lt - zt; ball_projection_grad(auxN, f_coeff * augm_ln, GP);
 +      e = gmm::vect_sp(GP, no, no) - f;
 +      ball_projection_grad_r(auxN, f_coeff * augm_ln, V);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = no[i]*no[j]*e - GP(i,j) + f_coeff*f*V[j]*no[i];
 +      break;
 +    case K_UL_FRICT_V4:
 +      f = Heav(r*(un-g)-ln);
 +      augm_ln = gmm::neg(ln - r*(un-g));
 +      auxN = lt - zt; ball_projection_grad(auxN, f_coeff * augm_ln, GP);
 +      e = alpha * gmm::vect_sp(GP, no, no) - f;
 +      ball_projection_grad_r(auxN, f_coeff * augm_ln, V);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = no[i]*no[j]*e - alpha*GP(i,j) + f_coeff * f * V[i] * no[j];
 +      break;
 +    case K_UL_FRICT_V5:
 +      e = (alpha-scalar_type(1));
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = no[i]*no[j]*e - ((i == j) ? alpha : scalar_type(0));
 +      break;
 +    case K_UL_FRICT_V7:
 +      De_Saxce_projection_grad(lnt, no, f_coeff, GP);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j) t[i*N+j] = -GP(j,i);
 +      break;
 +    case K_UL_FRICT_V8:
++=======
+       friction_law(gmm::neg(ln), rho, rho_grad);
+       ball_projection_grad(lt, rho, GP);
+       e = gmm::vect_sp(GP, no, no) - Heav(-ln);
+       coulomb = (rho_grad > 0) && bool(Heav(-ln));
+       if (coulomb) ball_projection_grad_r(lt, rho, V);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j)
+         t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
+                    (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0));
+       break;
+     case K_UL_FRICT_V3:
+       augm_ln = ln - r*(un-g);
+       friction_law(gmm::neg(augm_ln), rho, rho_grad);
+       auxN = lt - zt;
+       ball_projection_grad(auxN, rho, GP);
+       e = gmm::vect_sp(GP, no, no) - Heav(-augm_ln);
+       coulomb = (rho_grad > 0) && bool(Heav(-augm_ln));
+       if (coulomb) ball_projection_grad_r(auxN, rho, V);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j)
+         t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
+                    (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0));
+       break;
+     case K_UL_FRICT_V4:
+       augm_ln = ln - r*(un-g);
+       friction_law(gmm::neg(augm_ln), rho, rho_grad);
+       auxN = lt - zt;
+       ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
+       e = gmm::vect_sp(GP, no, no) - Heav(-augm_ln);
+       coulomb = (rho_grad > 0) && bool(Heav(-augm_ln));
+       if (coulomb) ball_projection_grad_r(auxN, rho, V);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j)
+         t[i*N+j] = no[i]*no[j]*e - GP(i,j) +
+                    (coulomb ? rho_grad*V[i]*no[j] : scalar_type(0));
+       break;
+     case K_UL_FRICT_V5:
+       e = alpha - scalar_type(1);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j)
+         t[i*N+j] = no[i]*no[j]*e - ((i == j) ? alpha : scalar_type(0));
+       break;
+     case K_UL_FRICT_V7: // ignores friction_law, assumes pure Coulomb friction
+       De_Saxce_projection_grad(lnt, no, f_coeff, GP);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j) t[i*N+j] = -GP(j,i);
+       break;
+     case K_UL_FRICT_V8: // ignores friction_law, assumes pure Coulomb friction
++>>>>>>> upstream
        {
          scalar_type nzt = gmm::vect_norm2(zt);
          gmm::copy(gmm::identity_matrix(), GP); gmm::scale(GP, alpha);
@@@ -252,60 -290,60 +418,115 @@@
        }
        break;
      case K_LL_FRICT_V1:
++<<<<<<< HEAD
 +      f = Heav(r*(un-g)-ln);
 +      augm_ln = gmm::neg(ln - r*(un-g));
 +      auxN = lt - zt; ball_projection_grad(auxN, f_coeff * augm_ln, GP);
 +      e = f/r - gmm::vect_sp(GP, no, no) / r;
 +      ball_projection_grad_r(auxN, f_coeff * augm_ln, V);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = no[i]*no[j]*e
 +          - (((i == j) ? scalar_type(1) : scalar_type(0)) - GP(i,j))/r
 +          - f_coeff * f * V[j] * no[i] / r;
 +      break;
 +    case K_LL_FRICT_V2:
 +      e = -Heav(ln) + scalar_type(1);
 +      ball_projection_grad(lt, f_coeff * gmm::neg(ln), GP);
 +      e -= gmm::vect_sp(GP, no, no);
 +      ball_projection_grad_r(lt, f_coeff * gmm::neg(ln), V);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = (no[i]*no[j]*e - ((i == j) ? scalar_type(1) : scalar_type(0)) + GP(i,j) - f_coeff*Heav(-ln)*no[i]*V[j])/r;
 +      break;
 +    case K_LL_FRICT_V4:
++=======
+       augm_ln = ln - r*(un-g);
+       friction_law(gmm::neg(augm_ln), rho, rho_grad);
+       auxN = lt - zt;
+       ball_projection_grad(auxN, rho, GP);
+       e = Heav(-augm_ln) - gmm::vect_sp(GP, no, no);
+       coulomb = (rho_grad > 0) && bool(Heav(-augm_ln));
+       if (coulomb) ball_projection_grad_r(auxN, rho, V);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j)
+         t[i*N+j] = (no[i]*no[j]*e + GP(i,j)
+                     - ((i == j) ? scalar_type(1) : scalar_type(0))
+                     - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0))) / r;
+       break;
+     case K_LL_FRICT_V2:
+       friction_law(gmm::neg(ln), rho, rho_grad);
+       ball_projection_grad(lt, rho, GP);
+       e = Heav(-ln) - gmm::vect_sp(GP, no, no);
+       coulomb = (rho_grad > 0) && bool(Heav(-ln));
+       if (coulomb) ball_projection_grad_r(lt, rho, V);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j)
+         t[i*N+j] = (no[i]*no[j]*e + GP(i,j)
+                     - ((i == j) ? scalar_type(1) : scalar_type(0))
+                     - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0))) / r;
+       break;
+     case K_LL_FRICT_V4: // ignores friction_law, assumes pure Coulomb friction
++>>>>>>> upstream
        De_Saxce_projection_grad(lnt, no, f_coeff, GP);
        for (i=0; i<N; ++i) for (j=0; j<N; ++j)
          t[i*N+j] = (GP(i,j) - ((i == j) ? scalar_type(1) : scalar_type(0)))/r;
        break;
      case K_UU_FRICT_V1:
++<<<<<<< HEAD
 +      e = r*Heav(r*(un-g)-ln);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j) t[i*N+j] = no[i]*no[j]*e;
 +      break;
 +    case K_UU_FRICT_V2:
 +      e = Heav(r*(un-g)-ln);
 +      auxN = lt - zt; ball_projection_grad(auxN, -f_coeff * ln, GP);
 +      e -= alpha*gmm::vect_sp(GP, no, no);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = r*(no[i]*no[j]*e + alpha*GP(i,j));
 +      break;
 +    case K_UU_FRICT_V3:
 +      f = Heav(r*(un-g)-ln);
 +      augm_ln = gmm::neg(ln - r*(un-g));
 +      auxN = lt - zt; ball_projection_grad(auxN, f_coeff * augm_ln, GP);
 +      e = f - alpha*gmm::vect_sp(GP, no, no);
 +      ball_projection_grad_r(auxN, f_coeff * augm_ln, V);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = r*(no[i]*no[j]*e + alpha*GP(i,j) - f_coeff*f*no[i]*V[j]);
 +      break;
 +    case K_UU_FRICT_V4:
 +      e = Heav(r*(un-g));
 +      augm_ln = gmm::neg(- r*(un-g));
 +      auxN = - zt; ball_projection_grad(auxN, f_coeff * augm_ln, GP);
 +      e -= alpha*gmm::vect_sp(GP, no, no);
 +      ball_projection_grad_r(auxN, f_coeff * augm_ln, V);
 +      for (i=0; i<N; ++i) for (j=0; j<N; ++j)
 +        t[i*N+j] = r*(no[i]*no[j]*e + alpha*GP(i,j)
 +                      - f_coeff*Heav(r*(un-g))*no[i]*V[j]);
 +      break;
 +    case K_UU_FRICT_V5:
++=======
+       e = r * Heav(r*(un-g)-ln);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j) t[i*N+j] = no[i]*no[j]*e;
+       break;
+     case K_UU_FRICT_V2:
+       friction_law(-ln, rho, rho_grad);
+       auxN = lt - zt;
+       ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
+       e = Heav(r*(un-g)-ln) - gmm::vect_sp(GP, no, no);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j)
+         t[i*N+j] = r*(no[i]*no[j]*e + GP(i,j));
+       break;
+     case K_UU_FRICT_V3:
+     case K_UU_FRICT_V4:
+       augm_ln = (option == K_UU_FRICT_V3) ? ln - r*(un-g) : - r*(un-g);
+       auxN = (option == K_UU_FRICT_V3) ? lt - zt : -zt;
+       friction_law(gmm::neg(augm_ln), rho, rho_grad);
+       ball_projection_grad(auxN, rho, GP); gmm::scale(GP, alpha);
+       e = Heav(-augm_ln) - gmm::vect_sp(GP, no, no);
+       coulomb = (rho_grad > 0) && bool(Heav(-augm_ln));
+       if (coulomb) ball_projection_grad_r(auxN, rho, V);
+       for (i=0; i<N; ++i) for (j=0; j<N; ++j)
+         t[i*N+j] = r*(no[i]*no[j]*e + GP(i,j)
+                       - (coulomb ? rho_grad*no[i]*V[j] : scalar_type(0)));
+       break;
+     case K_UU_FRICT_V5: // ignores friction_law, assumes pure Coulomb friction
++>>>>>>> upstream
        {
          scalar_type nzt = gmm::vect_norm2(zt);
          auxN = lnt - (r*(un-g) - f_coeff * nzt) * no - zt;
@@@ -336,23 -374,16 +557,35 @@@
  
      switch (nb) { // last is computed first
      case 1 : // calculate [un] and [zt] interpolating [U],[WT],[VT] on [mf_u]
++<<<<<<< HEAD
 +      coeff.resize(mf_u.nb_basic_dof_of_element(cv));
 +      gmm::copy(gmm::sub_vector
 +                (U, gmm::sub_index
 +                 (mf_u.ind_basic_dof_of_element(cv))), coeff);
++=======
+       slice_vector_on_basic_dof_of_element(mf_u, U, cv, coeff);
++>>>>>>> upstream
        ctx.pf()->interpolation(ctx, coeff, V, N);
        un = gmm::vect_sp(V, no);
        if (!contact_only) {
          if (gmm::vect_size(WT) == gmm::vect_size(U)) {
++<<<<<<< HEAD
 +          gmm::copy(gmm::sub_vector
 +                    (WT, gmm::sub_index
 +                     (mf_u.ind_basic_dof_of_element(cv))), coeff);
 +          ctx.pf()->interpolation(ctx, coeff, auxN, N);
 +          auxN -= gmm::vect_sp(auxN, no) * no;
 +          if (gmm::vect_size(VT) == gmm::vect_size(U)) {
 +            gmm::copy(gmm::sub_vector
 +                      (VT, gmm::sub_index
 +                       (mf_u.ind_basic_dof_of_element(cv))), coeff);
++=======
+           slice_vector_on_basic_dof_of_element(mf_u, WT, cv, coeff);
+           ctx.pf()->interpolation(ctx, coeff, auxN, N);
+           auxN -= gmm::vect_sp(auxN, no) * no;
+           if (gmm::vect_size(VT) == gmm::vect_size(U)) {
+             slice_vector_on_basic_dof_of_element(mf_u, VT, cv, coeff);
++>>>>>>> upstream
              ctx.pf()->interpolation(ctx, coeff, vt, N);
              vt -= gmm::vect_sp(vt, no) * no;
              // zt = r*(alpha*(u_T-w_T) + (1-gamma)*v_T)
@@@ -370,10 -401,7 +603,14 @@@
  
      case 2 : // calculate [g] and [no] interpolating [obs] on [mf_obs]
               // calculate [ln] and [lt] from [lnt] and [no]
++<<<<<<< HEAD
 +      coeff.resize(mf_obs.nb_basic_dof_of_element(cv));
 +      gmm::copy(gmm::sub_vector
 +                (obs, gmm::sub_index
 +                 (mf_obs.ind_basic_dof_of_element(cv))), coeff);
++=======
+       slice_vector_on_basic_dof_of_element(mf_obs, obs, cv, coeff);
++>>>>>>> upstream
        ctx.pf()->interpolation_grad(ctx, coeff, grad, 1);
        gmm::copy(gmm::mat_row(grad, 0), no);
        no /= -gmm::vect_norm2(no);
@@@ -389,10 -417,7 +626,14 @@@
  
      case 3 : // calculate [ln] or [lnt] interpolating [lambda] on [mf_lambda]
        if (pmf_lambda) {
++<<<<<<< HEAD
 +        coeff.resize(pmf_lambda->nb_basic_dof_of_element(cv));
 +        gmm::copy(gmm::sub_vector
 +                  (lambda, gmm::sub_index
 +                   (pmf_lambda->ind_basic_dof_of_element(cv))), coeff);
++=======
+         slice_vector_on_basic_dof_of_element(*pmf_lambda, lambda, cv, coeff);
++>>>>>>> upstream
          if (contact_only) {
            ctx.pf()->interpolation(ctx, coeff, aux1, 1);
            ln = aux1[0];
@@@ -402,15 -427,24 +643,36 @@@
        }
        break;
  
++<<<<<<< HEAD
 +    case 4 :// calculate [f_coeff] interpolating [friction_coeff] on [mf_coeff]
 +      GMM_ASSERT1(!contact_only, "Invalid friction option");
 +      if (pmf_coeff) {
 +        coeff.resize(pmf_coeff->nb_basic_dof_of_element(cv));
 +        gmm::copy(gmm::sub_vector
 +                  (friction_coeff, gmm::sub_index
 +                   (pmf_coeff->ind_basic_dof_of_element(cv))), coeff);
 +        ctx.pf()->interpolation(ctx, coeff, aux1, 1);
 +        f_coeff = aux1[0];
++=======
+     case 4 : // calculate [f_coeff] interpolating [friction_coeff] on [mf_coeff]
+              // calculate [tau_adh] interpolating [tau_adhesion] on [mf_coeff]
+              // calculate [tresca_lim] interpolating [tresca_limit] on [mf_coeff]
+       GMM_ASSERT1(!contact_only, "Invalid friction option");
+       if (pmf_coeff) {
+         slice_vector_on_basic_dof_of_element(*pmf_coeff, friction_coeff, cv, coeff);
+         ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+         f_coeff = aux1[0];
+         if (gmm::vect_size(tau_adhesion)) {
+           slice_vector_on_basic_dof_of_element(*pmf_coeff, tau_adhesion, cv, coeff);
+           ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+           tau_adh = aux1[0];
+           if (gmm::vect_size(tresca_limit)) {
+             slice_vector_on_basic_dof_of_element(*pmf_coeff, tresca_limit, cv, coeff);
+             ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+             tresca_lim = aux1[0];
+           }
+         }
++>>>>>>> upstream
        }
        break;
  
@@@ -442,23 -476,21 +704,41 @@@
      switch (nb) { // last is computed first
      case 1 : // calculate [un] and [zt] interpolating [U1],[WT1] on [mf_u1]
               // and subtracting [un] and [zt] calculated on [mf_u2]
++<<<<<<< HEAD
 +      coeff.resize(mf_u1.nb_basic_dof_of_element(cv));
 +      gmm::copy(gmm::sub_vector
 +                (U1, gmm::sub_index
 +                 (mf_u1.ind_basic_dof_of_element(cv))), coeff);
 +      ctx.pf()->interpolation(ctx, coeff, V, N);
 +      un = gmm::vect_sp(V, no) - un;
 +      if (!contact_only) {
 +        if (gmm::vect_size(WT1) == gmm::vect_size(U1)) {
 +          gmm::copy(gmm::sub_vector
 +                    (WT1, gmm::sub_index
 +                     (mf_u1.ind_basic_dof_of_element(cv))), coeff);
 +          ctx.pf()->interpolation(ctx, coeff, auxN, N);
 +          auxN -= gmm::vect_sp(auxN, no) * no;
 +          zt = ((V - un * no) - auxN) * (r * alpha) - zt; // zt = r*alpha*(u_T-w_T)
 +        } else {
 +          zt = (V - un * no) * (r * alpha) - zt;          // zt = r*alpha*u_T
 +        }
++=======
+       slice_vector_on_basic_dof_of_element(mf_u1, U1, cv, coeff);
+       ctx.pf()->interpolation(ctx, coeff, V, N);
+       {
+         scalar_type un1 = gmm::vect_sp(V, no);
+         if (!contact_only) {
+           if (gmm::vect_size(WT1) == gmm::vect_size(U1)) {
+             slice_vector_on_basic_dof_of_element(mf_u1, WT1, cv, coeff);
+             ctx.pf()->interpolation(ctx, coeff, auxN, N);
+             auxN -= gmm::vect_sp(auxN, no) * no;
+             zt = ((V - un1 * no) - auxN) * (r * alpha) - zt; // = zt1 - zt2 , with zt = r*alpha*(u_T-w_T)
+           } else {
+             zt = (V - un1 * no) * (r * alpha) - zt;          // = zt1 - zt2 , with zt = r*alpha*u_T
+           }
+         }
+         un = un1 - un; // = un1 - un2
++>>>>>>> upstream
        }
        break;
  
@@@ -476,17 -508,12 +756,25 @@@
          lt = lnt - ln * no;
        }
  
++<<<<<<< HEAD
 +      coeff.resize(mf_u2.nb_basic_dof_of_element(cv));
 +      gmm::copy(gmm::sub_vector
 +                (U2, gmm::sub_index
 +                 (mf_u2.ind_basic_dof_of_element(cv))), coeff);
++=======
+       slice_vector_on_basic_dof_of_element(mf_u2, U2, cv, coeff);
++>>>>>>> upstream
        ctx.pf()->interpolation(ctx, coeff, V, N);
        un = gmm::vect_sp(V, no);
        if (!contact_only) {
          if (gmm::vect_size(WT2) == gmm::vect_size(U2)) {
++<<<<<<< HEAD
 +          gmm::copy(gmm::sub_vector
 +                    (WT2, gmm::sub_index
 +                     (mf_u2.ind_basic_dof_of_element(cv))), coeff);
++=======
+           slice_vector_on_basic_dof_of_element(mf_u2, WT2, cv, coeff);
++>>>>>>> upstream
            ctx.pf()->interpolation(ctx, coeff, auxN, N);
            auxN -= gmm::vect_sp(auxN, no) * no;
            zt = ((V - un * no) - auxN) * (r * alpha); // zt = r*alpha*(u_T-w_T)
@@@ -498,10 -525,7 +786,14 @@@
  
      case 3 : // calculate [ln] or [lnt] interpolating [lambda] on [mf_lambda]
        if (pmf_lambda) {
++<<<<<<< HEAD
 +        coeff.resize(pmf_lambda->nb_basic_dof_of_element(cv));
 +        gmm::copy(gmm::sub_vector
 +                  (lambda, gmm::sub_index
 +                   (pmf_lambda->ind_basic_dof_of_element(cv))), coeff);
++=======
+         slice_vector_on_basic_dof_of_element(*pmf_lambda, lambda, cv, coeff);
++>>>>>>> upstream
          if (contact_only) {
            ctx.pf()->interpolation(ctx, coeff, aux1, 1);
            ln = aux1[0];
@@@ -511,15 -535,24 +803,36 @@@
        }
        break;
  
++<<<<<<< HEAD
 +    case 4 :// calculate [f_coeff] interpolating [friction_coeff] on [mf_coeff]
 +      GMM_ASSERT1(!contact_only, "Invalid friction option");
 +      if (pmf_coeff) {
 +        coeff.resize(pmf_coeff->nb_basic_dof_of_element(cv));
 +        gmm::copy(gmm::sub_vector
 +                  (friction_coeff, gmm::sub_index
 +                   (pmf_coeff->ind_basic_dof_of_element(cv))), coeff);
 +        ctx.pf()->interpolation(ctx, coeff, aux1, 1);
 +        f_coeff = aux1[0];
++=======
+     case 4 : // calculate [f_coeff] interpolating [friction_coeff] on [mf_coeff]
+              // calculate [tau_adh] interpolating [tau_adhesion] on [mf_coeff]
+              // calculate [tresca_lim] interpolating [tresca_limit] on [mf_coeff]
+       GMM_ASSERT1(!contact_only, "Invalid friction option");
+       if (pmf_coeff) {
+         slice_vector_on_basic_dof_of_element(*pmf_coeff, friction_coeff, cv, coeff);
+         ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+         f_coeff = aux1[0];
+         if (gmm::vect_size(tau_adhesion)) {
+           slice_vector_on_basic_dof_of_element(*pmf_coeff, tau_adhesion, cv, coeff);
+           ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+           tau_adh = aux1[0];
+           if (gmm::vect_size(tresca_limit)) {
+             slice_vector_on_basic_dof_of_element(*pmf_coeff, tresca_limit, cv, coeff);
+             ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+             tresca_lim = aux1[0];
+           }
+         }
++>>>>>>> upstream
        }
        break;
  
@@@ -545,7 -578,7 +858,11 @@@
     scalar_type r, const mesh_region &rg, int option = 1) {
  
      size_type subterm1 = (option == 3) ? K_UL_V2 : K_UL_V1;
++<<<<<<< HEAD
 +    size_type subterm2 = (option == 3) ? K_UL_V4 : K_UL_V3;
++=======
+     size_type subterm2 = (option == 3) ? K_UL_V1 : K_UL_V3;
++>>>>>>> upstream
      size_type subterm3 = (option == 3) ? K_LL_V2 : K_LL_V1;
      size_type subterm4 = (option == 2) ? K_UU_V2 : K_UU_V1;
  
@@@ -592,7 -625,7 +909,11 @@@
     const getfem::mesh_fem &mf_u, const VECT1 &U,
     const getfem::mesh_fem &mf_obs, const VECT1 &obs,
     const getfem::mesh_fem &mf_lambda, const VECT1 &lambda,
++<<<<<<< HEAD
 +   const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeff, scalar_type r,
++=======
+    const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeffs, scalar_type r,
++>>>>>>> upstream
     scalar_type alpha, const VECT1 *WT,
     scalar_type gamma, const VECT1 *VT,
     const mesh_region &rg, int option = 1) {
@@@ -614,13 -647,13 +935,23 @@@
  
      contact_rigid_obstacle_nonlinear_term
        nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
++<<<<<<< HEAD
 +             pmf_coeff, f_coeff, alpha, WT, gamma, VT),
 +      nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
 +             pmf_coeff, f_coeff, alpha, WT, gamma, VT),
 +      nterm3(subterm3, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
 +             pmf_coeff, f_coeff, alpha, WT, gamma, VT),
 +      nterm4(subterm4, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
 +             pmf_coeff, f_coeff, alpha, WT, gamma, VT);
++=======
+              pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
+       nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
+              pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
+       nterm3(subterm3, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
+              pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
+       nterm4(subterm4, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
+              pmf_coeff, f_coeffs, alpha, WT, gamma, VT);
++>>>>>>> upstream
  
      const std::string aux_fems = pmf_coeff ? "#1,#2,#3,#4" : "#1,#2,#3";
  
@@@ -701,7 -734,7 +1032,11 @@@
     const getfem::mesh_fem &mf_u, const VECT1 &U,
     const getfem::mesh_fem &mf_obs, const VECT1 &obs,
     const getfem::mesh_fem &mf_lambda, const VECT1 &lambda,
++<<<<<<< HEAD
 +   const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeff, scalar_type r,
++=======
+    const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeffs, scalar_type r,
++>>>>>>> upstream
     scalar_type alpha, const VECT1 *WT,
     scalar_type gamma, const VECT1 *VT,
     const mesh_region &rg, int option = 1) {
@@@ -717,9 -750,9 +1052,15 @@@
  
      contact_rigid_obstacle_nonlinear_term
        nterm1(subterm1, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
++<<<<<<< HEAD
 +             pmf_coeff, f_coeff, alpha, WT, gamma, VT),
 +      nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
 +             pmf_coeff, f_coeff, alpha, WT, gamma, VT);
++=======
+              pmf_coeff, f_coeffs, alpha, WT, gamma, VT),
+       nterm2(subterm2, r, mf_u, U, mf_obs, obs, &mf_lambda, &lambda,
+              pmf_coeff, f_coeffs, alpha, WT, gamma, VT);
++>>>>>>> upstream
  
      const std::string aux_fems = pmf_coeff ? "#1,#2,#3,#4" : "#1,#2,#3";
  
@@@ -741,13 -774,13 +1082,21 @@@
  
    struct integral_contact_rigid_obstacle_brick : public virtual_brick {
  
++<<<<<<< HEAD
 +    bool Tresca_version, contact_only;
++=======
+     bool contact_only;
++>>>>>>> upstream
      int option;
  
      // option = 1 : Alart-Curnier
      // option = 2 : symmetric Alart-Curnier (with friction, almost symmetric),
      // option = 3 : Unsymmetric method based on augmented multipliers
++<<<<<<< HEAD
 +    // option = 4 : Unsymmetric method based on augmented multipliers 
++=======
+     // option = 4 : Unsymmetric method based on augmented multipliers
++>>>>>>> upstream
      //              with De-Saxce projection.
  
      virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
@@@ -774,7 -807,7 +1123,11 @@@
        //             frictionless case and vector valued in the case with
        //             friction.
        // data      : obstacle, r for the version without friction
++<<<<<<< HEAD
 +      //           : obstacle, r, friction_coeff, alpha, w_t, gamma, v_t for
++=======
+       //           : obstacle, r, friction_coeffs, alpha, w_t, gamma, v_t for
++>>>>>>> upstream
        //             the version with friction. alpha, w_t , gamma and v_t
        //             are optional and equal to 1, 0, 1 and 0 by default,
        //             respectively.
@@@ -796,12 -829,13 +1149,22 @@@
        GMM_ASSERT1(gmm::vect_size(vr) == 1, "Parameter r should be a scalar");
        const mesh_im &mim = *mims[0];
  
++<<<<<<< HEAD
 +      const model_real_plain_vector &friction_coeff
 +        = contact_only ? u : md.real_variable(dl[2]);
 +      const mesh_fem *pmf_coeff = contact_only ? 0 : md.pmesh_fem_of_variable(dl[2]);
 +      sl = gmm::vect_size(friction_coeff);
 +      if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
 +      GMM_ASSERT1(sl == 1 || contact_only,
++=======
+       const model_real_plain_vector dummy_vec(0);
+       const model_real_plain_vector &friction_coeffs = contact_only
+                                                      ? dummy_vec : md.real_variable(dl[2]);
+       const mesh_fem *pmf_coeff = contact_only ? 0 : md.pmesh_fem_of_variable(dl[2]);
+       sl = gmm::vect_size(friction_coeffs);
+       if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
+       GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3 || contact_only,
++>>>>>>> upstream
                    "the data corresponding to the friction coefficient "
                    "has not the right format");
  
@@@ -812,14 -846,19 +1175,30 @@@
                      "Parameter alpha should be a scalar");
        }
  
++<<<<<<< HEAD
 +      const model_real_plain_vector *WT
 +        = (!contact_only && dl.size()>=5) ? &(md.real_variable(dl[4])) : 0;
 +
 +      scalar_type gamma = 1;
 +      if (!contact_only && dl.size() >= 6) {
 +        gamma = md.real_variable(dl[5])[0];
 +        GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[5])) == 1,
 +                    "Parameter gamma should be a scalar");
++=======
+       const model_real_plain_vector *WT = 0;
+       if (!contact_only && dl.size() >= 5) {
+         if (dl[4].compare(vl[0]) != 0)
+           WT = &(md.real_variable(dl[4]));
+         else if (md.n_iter_of_variable(vl[0]) > 1)
+           WT = &(md.real_variable(vl[0],1));
+       }
+ 
+       scalar_type gamma = 1;
+       if (!contact_only && dl.size() >= 6) {
+         GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[5])) == 1,
+                     "Parameter gamma should be a scalar");
+         gamma = md.real_variable(dl[5])[0];
++>>>>>>> upstream
        }
  
        const model_real_plain_vector *VT
@@@ -842,7 -881,7 +1221,11 @@@
            asm_Alart_Curnier_contact_rigid_obstacle_tangent_matrix
              (matl[0], matl[1], matl[2], matl[fourthmat], mim,
               mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda,
++<<<<<<< HEAD
 +             pmf_coeff, &friction_coeff, vr[0], alpha, WT, gamma, VT,
++=======
+              pmf_coeff, &friction_coeffs, vr[0], alpha, WT, gamma, VT,
++>>>>>>> upstream
               rg, option);
        }
  
@@@ -859,14 -898,13 +1242,21 @@@
            asm_Alart_Curnier_contact_rigid_obstacle_rhs
              (vecl[0], vecl[2], mim,
               mf_u, u, mf_obstacle, obstacle, mf_lambda, lambda,
++<<<<<<< HEAD
 +             pmf_coeff, &friction_coeff, vr[0], alpha, WT, gamma, VT,
++=======
+              pmf_coeff, &friction_coeffs, vr[0], alpha, WT, gamma, VT,
++>>>>>>> upstream
               rg, option);
        }
  
      }
  
      integral_contact_rigid_obstacle_brick(bool contact_only_, int option_) {
++<<<<<<< HEAD
 +      Tresca_version = false;   // for future version ...
++=======
++>>>>>>> upstream
        option = option_;
        contact_only = contact_only_;
        set_flags(contact_only
@@@ -928,7 -966,7 +1318,11 @@@
    size_type add_integral_contact_with_rigid_obstacle_brick
    (model &md, const mesh_im &mim, const std::string &varname_u,
     const std::string &multname, const std::string &dataname_obs,
++<<<<<<< HEAD
 +   const std::string &dataname_r, const std::string &dataname_friction_coeff,
++=======
+    const std::string &dataname_r, const std::string &dataname_friction_coeffs,
++>>>>>>> upstream
     size_type region, int option,
     const std::string &dataname_alpha, const std::string &dataname_wt,
     const std::string &dataname_gamma, const std::string &dataname_vt) {
@@@ -955,7 -993,7 +1349,11 @@@
      }
      model::varnamelist dl(1, dataname_obs);
      dl.push_back(dataname_r);
++<<<<<<< HEAD
 +    dl.push_back(dataname_friction_coeff);
++=======
+     dl.push_back(dataname_friction_coeffs);
++>>>>>>> upstream
      if (dataname_alpha.size()) {
        dl.push_back(dataname_alpha);
        if (dataname_wt.size()) {
@@@ -1040,7 -1078,7 +1438,11 @@@
     const getfem::mesh_fem &mf_u, const VECT1 &U,
     const getfem::mesh_fem &mf_obs, const VECT1 &obs,
     const getfem::mesh_fem *pmf_lambda, const VECT1 *lambda,
++<<<<<<< HEAD
 +   const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeff, scalar_type r,
++=======
+    const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeffs, scalar_type r,
++>>>>>>> upstream
     scalar_type alpha, const VECT1 *WT,
     const mesh_region &rg, int option = 1) {
  
@@@ -1053,7 -1091,7 +1455,11 @@@
  
      contact_rigid_obstacle_nonlinear_term
        nterm(subterm, r, mf_u, U, mf_obs, obs, pmf_lambda, lambda,
++<<<<<<< HEAD
 +            pmf_coeff, f_coeff, alpha, WT);
++=======
+             pmf_coeff, f_coeffs, alpha, WT);
++>>>>>>> upstream
  
      const std::string aux_fems = pmf_coeff ? "#1,#2,#3,#4"
                                             : (pmf_lambda ? "#1,#2,#3": "#1,#2");
@@@ -1084,7 -1122,7 +1490,11 @@@
     const getfem::mesh_fem &mf_u, const VECT1 &U,
     const getfem::mesh_fem &mf_obs, const VECT1 &obs,
     const getfem::mesh_fem *pmf_lambda, const VECT1 *lambda,
++<<<<<<< HEAD
 +   const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeff, scalar_type r,
++=======
+    const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeffs, scalar_type r,
++>>>>>>> upstream
     scalar_type alpha, const VECT1 *WT,
     const mesh_region &rg, int option = 1) {
  
@@@ -1097,7 -1135,7 +1507,11 @@@
  
      contact_rigid_obstacle_nonlinear_term
        nterm(subterm, r, mf_u, U, mf_obs, obs, pmf_lambda, lambda,
++<<<<<<< HEAD
 +            pmf_coeff, f_coeff, alpha, WT);
++=======
+             pmf_coeff, f_coeffs, alpha, WT);
++>>>>>>> upstream
  
      const std::string aux_fems = pmf_coeff ? "#1,#2,#3,#4"
                                             : (pmf_lambda ? "#1,#2,#3": "#1,#2");
@@@ -1123,7 -1161,7 +1537,11 @@@
  
    struct penalized_contact_rigid_obstacle_brick : public virtual_brick {
  
++<<<<<<< HEAD
 +    bool Tresca_version, contact_only;
++=======
+     bool contact_only;
++>>>>>>> upstream
      int option;
  
      virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
@@@ -1148,7 -1186,7 +1566,11 @@@
  
        size_type N = mf_u.linked_mesh().dim();
  
++<<<<<<< HEAD
 +      // Data : obs, r, [lambda,] [friction_coeff,] [alpha,] [WT]
++=======
+       // Data : obs, r, [lambda,] [friction_coeffs,] [alpha,] [WT]
++>>>>>>> upstream
        size_type nb_data_1 = ((option == 1) ? 2 : 3) + (contact_only ? 0 : 1);
        size_type nb_data_2 = nb_data_1 + (contact_only ? 0 : 2);
        GMM_ASSERT1(dl.size() >= nb_data_1 && dl.size() <= nb_data_2,
@@@ -1179,17 -1217,17 +1601,29 @@@
                      "has not the right format");
        }
  
++<<<<<<< HEAD
 +      const model_real_plain_vector *f_coeff = 0;
++=======
+       const model_real_plain_vector *f_coeffs = 0;
++>>>>>>> upstream
        const mesh_fem *pmf_coeff = 0;
        scalar_type alpha = 1;
        const model_real_plain_vector *WT = 0;
        if (!contact_only) {
          nd++;
++<<<<<<< HEAD
 +        f_coeff = &(md.real_variable(dl[nd]));
 +        pmf_coeff = md.pmesh_fem_of_variable(dl[nd]);
 +        sl = gmm::vect_size(*f_coeff);
 +        if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
 +        GMM_ASSERT1(sl == 1,
++=======
+         f_coeffs = &(md.real_variable(dl[nd]));
+         pmf_coeff = md.pmesh_fem_of_variable(dl[nd]);
+         sl = gmm::vect_size(*f_coeffs);
+         if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
+         GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3,
++>>>>>>> upstream
                      "the data corresponding to the friction coefficient "
                      "has not the right format");
          if (dl.size() > nd+1) {
@@@ -1201,7 -1239,10 +1635,14 @@@
  
          if (dl.size() > nd+1) {
            nd++;
++<<<<<<< HEAD
 +          WT = &(md.real_variable(dl[nd]));
++=======
+           if (dl[nd].compare(vl[0]) != 0)
+             WT = &(md.real_variable(dl[nd]));
+           else if (md.n_iter_of_variable(vl[0]) > 1)
+             WT = &(md.real_variable(vl[0],1));
++>>>>>>> upstream
          }
        }
  
@@@ -1221,7 -1262,7 +1662,11 @@@
          else
            asm_penalized_contact_rigid_obstacle_tangent_matrix
              (matl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
++<<<<<<< HEAD
 +             pmf_coeff, f_coeff, vr[0], alpha, WT, rg, option);
++=======
+              pmf_coeff, f_coeffs, vr[0], alpha, WT, rg, option);
++>>>>>>> upstream
        }
  
        if (version & model::BUILD_RHS) {
@@@ -1233,13 -1274,12 +1678,20 @@@
          else
            asm_penalized_contact_rigid_obstacle_rhs
              (vecl[0], mim, mf_u, u, mf_obs, obs, pmf_lambda, lambda,
++<<<<<<< HEAD
 +             pmf_coeff, f_coeff, vr[0], alpha, WT, rg, option);
++=======
+              pmf_coeff, f_coeffs, vr[0], alpha, WT, rg, option);
++>>>>>>> upstream
        }
  
      }
  
      penalized_contact_rigid_obstacle_brick(bool contact_only_, int option_) {
++<<<<<<< HEAD
 +      Tresca_version = false;   // for future version ...
++=======
++>>>>>>> upstream
        contact_only = contact_only_;
        option = option_;
        set_flags(contact_only
@@@ -1289,7 -1329,7 +1741,11 @@@
    size_type add_penalized_contact_with_rigid_obstacle_brick
    (model &md, const mesh_im &mim, const std::string &varname_u,
     const std::string &dataname_obs, const std::string &dataname_r,
++<<<<<<< HEAD
 +   const std::string &dataname_friction_coeff,
++=======
+    const std::string &dataname_friction_coeffs,
++>>>>>>> upstream
     size_type region, int option, const std::string &dataname_lambda,
     const std::string &dataname_alpha, const std::string &dataname_wt) {
  
@@@ -1305,7 -1345,7 +1761,11 @@@
      case 2: case 3: dl.push_back(dataname_lambda); break;
      default: GMM_ASSERT1(false, "Penalized contact brick : invalid option");
      }
++<<<<<<< HEAD
 +    dl.push_back(dataname_friction_coeff);
++=======
+     dl.push_back(dataname_friction_coeffs);
++>>>>>>> upstream
      if (dataname_alpha.size() > 0) {
        dl.push_back(dataname_alpha);
        if (dataname_wt.size() > 0) dl.push_back(dataname_wt);
@@@ -1334,7 -1374,7 +1794,11 @@@
     scalar_type r, const mesh_region &rg, int option = 1) {
  
      size_type subterm1 = (option == 3) ? K_UL_V2 : K_UL_V1;
++<<<<<<< HEAD
 +    size_type subterm2 = (option == 3) ? K_UL_V4 : K_UL_V3;
++=======
+     size_type subterm2 = (option == 3) ? K_UL_V1 : K_UL_V3;
++>>>>>>> upstream
      size_type subterm3 = (option == 3) ? K_LL_V2 : K_LL_V1;
      size_type subterm4 = (option == 2) ? K_UU_V2 : K_UU_V1;
  
@@@ -1391,12 -1431,12 +1855,20 @@@
    template<typename MAT, typename VEC>
    void asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix // with friction
    (MAT &Ku1l, MAT &Klu1, MAT &Ku2l, MAT &Klu2, MAT &Kll,
++<<<<<<< HEAD
 +   MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2,
++=======
+    MAT &Ku1u1, MAT &Ku2u2, MAT &Ku1u2, MAT &Ku2u1,
++>>>>>>> upstream
     const mesh_im &mim,
     const getfem::mesh_fem &mf_u1, const VEC &U1,
     const getfem::mesh_fem &mf_u2, const VEC &U2,
     const getfem::mesh_fem &mf_lambda, const VEC &lambda,
++<<<<<<< HEAD
 +   const getfem::mesh_fem *pmf_coeff, const VEC *f_coeff,
++=======
+    const getfem::mesh_fem *pmf_coeff, const VEC *f_coeffs,
++>>>>>>> upstream
     scalar_type r, scalar_type alpha,
     const VEC *WT1, const VEC *WT2,
     const mesh_region &rg, int option = 1) {
@@@ -1422,13 -1462,13 +1894,23 @@@
  
      contact_nonmatching_meshes_nonlinear_term
        nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
++<<<<<<< HEAD
 +             pmf_coeff, f_coeff, alpha, WT1, WT2),
 +      nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
 +             pmf_coeff, f_coeff, alpha, WT1, WT2),
 +      nterm3(subterm3, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
 +             pmf_coeff, f_coeff, alpha, WT1, WT2),
 +      nterm4(subterm4, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
 +             pmf_coeff, f_coeff, alpha, WT1, WT2);
++=======
+              pmf_coeff, f_coeffs, alpha, WT1, WT2),
+       nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
+              pmf_coeff, f_coeffs, alpha, WT1, WT2),
+       nterm3(subterm3, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
+              pmf_coeff, f_coeffs, alpha, WT1, WT2),
+       nterm4(subterm4, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
+              pmf_coeff, f_coeffs, alpha, WT1, WT2);
++>>>>>>> upstream
  
      const std::string aux_fems = pmf_coeff ? "#1,#2,#3,#4" : "#1,#2,#3";
  
@@@ -1451,7 -1491,8 +1933,12 @@@
          "M$5(#3,#3)+=comp(NonLin$3(#1," + aux_fems + ").vBase(#3).vBase(#3))(i,j,:,i,:,j); " // LL
          "M$6(#1,#1)+=comp(NonLin$4(#1," + aux_fems + ").vBase(#1).vBase(#1))(i,j,:,i,:,j); " // U1U1
          "M$7(#2,#2)+=comp(NonLin$4(#1," + aux_fems + ").vBase(#2).vBase(#2))(i,j,:,i,:,j); " // U2U2
++<<<<<<< HEAD
 +        "M$8(#1,#2)+=comp(NonLin$4(#1," + aux_fems + ").vBase(#1).vBase(#2))(i,j,:,i,:,j)"); // U1U2
++=======
+         "M$8(#1,#2)+=comp(NonLin$4(#1," + aux_fems + ").vBase(#1).vBase(#2))(i,j,:,i,:,j); " // U1U2
+         "M$9(#2,#1)+=comp(NonLin$4(#1," + aux_fems + ").vBase(#2).vBase(#1))(i,j,:,i,:,j)"); // U2U1
++>>>>>>> upstream
        break;
      }
      assem.push_mi(mim);
@@@ -1472,6 -1513,7 +1959,10 @@@
      assem.push_mat(Ku1u1);
      assem.push_mat(Ku2u2);
      assem.push_mat(Ku1u2);
++<<<<<<< HEAD
++=======
+     assem.push_mat(Ku2u1);
++>>>>>>> upstream
      assem.assembly(rg);
  
      gmm::scale(Ku2l, scalar_type(-1));
@@@ -1526,7 -1568,7 +2017,11 @@@
     const getfem::mesh_fem &mf_u1, const VECT1 &U1,
     const getfem::mesh_fem &mf_u2, const VECT1 &U2,
     const getfem::mesh_fem &mf_lambda, const VECT1 &lambda,
++<<<<<<< HEAD
 +   const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeff,
++=======
+    const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeffs,
++>>>>>>> upstream
     scalar_type r, scalar_type alpha,
     const VECT1 *WT1, const VECT1 *WT2,
     const mesh_region &rg, int option = 1) {
@@@ -1542,9 -1584,9 +2037,15 @@@
  
      contact_nonmatching_meshes_nonlinear_term
        nterm1(subterm1, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
++<<<<<<< HEAD
 +             pmf_coeff, f_coeff, alpha, WT1, WT2),
 +      nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
 +             pmf_coeff, f_coeff, alpha, WT1, WT2);
++=======
+              pmf_coeff, f_coeffs, alpha, WT1, WT2),
+       nterm2(subterm2, r, mf_u1, U1, mf_u2, U2, &mf_lambda, &lambda,
+              pmf_coeff, f_coeffs, alpha, WT1, WT2);
++>>>>>>> upstream
  
      const std::string aux_fems = pmf_coeff ? "#1,#2,#3,#4" : "#1,#2,#3";
  
@@@ -1572,9 -1614,8 +2073,14 @@@
  
      size_type rg1, rg2; // ids of mesh regions on mf_u1 and mf_u2 that are
                          // expected to come in contact.
++<<<<<<< HEAD
 +    mutable getfem::pfem pfem_proj;        // cached fem and mesh_fem for the
 +    mutable getfem::mesh_fem *pmf_u2_proj; // projection between nonmatching meshes
 +    bool Tresca_version, contact_only;
++=======
+     mutable getfem::pfem pfem_proj; // cached fem for the projection between nonmatching meshes
+     bool contact_only;
++>>>>>>> upstream
      int option;
  
      // option = 1 : Alart-Curnier
@@@ -1610,7 -1651,7 +2116,11 @@@
        GMM_ASSERT1(mf_lambda.get_qdim() == (contact_only ? 1 : mf_u1.get_qdim()),
                    "The contact stress variable has not the right dimension");
  
++<<<<<<< HEAD
 +      // Data : r, [friction_coeff,] [alpha,] [WT1, WT2]
++=======
+       // Data : r, [friction_coeffs,] [alpha,] [WT1, WT2]
++>>>>>>> upstream
        //     alpha, WT1, WT2 are optional and equal to 1, 0 and 0 by default respectively.
        if (contact_only) {
          GMM_ASSERT1(dl.size() == 1,
@@@ -1625,16 -1666,16 +2135,29 @@@
        const model_real_plain_vector &vr = md.real_variable(dl[0]);
        GMM_ASSERT1(gmm::vect_size(vr) == 1, "Parameter r should be a scalar");
  
++<<<<<<< HEAD
 +      const model_real_plain_vector *f_coeff = 0, *WT1 = 0, *WT2 = 0;
 +      const mesh_fem *pmf_coeff = 0;
 +      scalar_type alpha = 1;
 +      if (!contact_only) {
 +        f_coeff = &(md.real_variable(dl[1]));
 +        pmf_coeff = md.pmesh_fem_of_variable(dl[1]);
 +
 +        size_type sl = gmm::vect_size(*f_coeff);
 +        if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
 +        GMM_ASSERT1(sl == 1,
++=======
+       const model_real_plain_vector *f_coeffs = 0, *WT1 = 0, *WT2 = 0;
+       const mesh_fem *pmf_coeff = 0;
+       scalar_type alpha = 1;
+       if (!contact_only) {
+         f_coeffs = &(md.real_variable(dl[1]));
+         pmf_coeff = md.pmesh_fem_of_variable(dl[1]);
+ 
+         size_type sl = gmm::vect_size(*f_coeffs);
+         if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
+         GMM_ASSERT1(sl == 1 || sl == 2 || sl ==3,
++>>>>>>> upstream
                      "the data corresponding to the friction coefficient "
                      "has not the right format");
  
@@@ -1644,17 -1685,26 +2167,38 @@@
                        "Parameter alpha should be a scalar");
          }
  
++<<<<<<< HEAD
 +        if (dl.size() >= 4)
 +          WT1 = &(md.real_variable(dl[3]));
 +
 +        if (dl.size() >= 5)
 +          WT2 = &(md.real_variable(dl[4]));
++=======
+         if (dl.size() >= 4) {
+           if (dl[3].compare(vl[0]) != 0)
+             WT1 = &(md.real_variable(dl[3]));
+           else if (md.n_iter_of_variable(vl[0]) > 1)
+             WT1 = &(md.real_variable(vl[0],1));
+         }
+ 
+         if (dl.size() >= 5) {
+           if (dl[4].compare(vl[1]) != 0)
+             WT2 = &(md.real_variable(dl[4]));
+           else if (md.n_iter_of_variable(vl[1]) > 1)
+             WT2 = &(md.real_variable(vl[1],1));
+         }
++>>>>>>> upstream
        }
  
        // Matrix terms (T_u1l, T_lu1, T_u2l, T_lu2, T_ll, T_u1u1, T_u2u2, T_u1u2)
        GMM_ASSERT1(matl.size() == size_type(3 +                                // U1L, U2L, LL
                                             2 * !is_symmetric() +              // LU1, LU2
++<<<<<<< HEAD
 +                                           3 * (option == 2)), // U1U1, U2U2, U1U2
++=======
+                                            3 * (option == 2) + // U1U1, U2U2, U1U2
+                                            1 * (option == 2 && !is_symmetric())), // U2U1
++>>>>>>> upstream
                    "Wrong number of terms for "
                    "integral contact between nonmatching meshes brick");
  
@@@ -1664,30 -1714,26 +2208,52 @@@
        size_type N = mf_u1.linked_mesh().dim();
  
        // projection of the second mesh_fem onto the mesh of the first mesh_fem
++<<<<<<< HEAD
 +      if (!pmf_u2_proj) {
 +        pmf_u2_proj = new getfem::mesh_fem(mim.linked_mesh(), dim_type(N));
 +        pfem_proj = new_projected_fem(mf_u2, mim, rg2, rg1);
 +        pmf_u2_proj->set_finite_element(mim.linked_mesh().convex_index(), pfem_proj);
 +      }
++=======
+       if (!pfem_proj)
+         pfem_proj = new_projected_fem(mf_u2, mim, rg2, rg1);
+ 
+       getfem::mesh_fem mf_u2_proj(mim.linked_mesh(), dim_type(N));
+       mf_u2_proj.set_finite_element(mim.linked_mesh().convex_index(), pfem_proj);
++>>>>>>> upstream
  
        size_type nbdof1 = mf_u1.nb_dof();
        size_type nbdof_lambda = mf_lambda.nb_dof();
        size_type nbdof2 = mf_u2.nb_dof();
++<<<<<<< HEAD
 +      size_type nbsub = pmf_u2_proj->nb_basic_dof();
 +
 +      std::vector<size_type> ind;
 +      pmf_u2_proj->get_global_dof_index(ind);
 +      gmm::unsorted_sub_index SUBI(ind);
 +
 +      gmm::csc_matrix<scalar_type> Rsub(nbdof2, nbsub), Esub(nbsub, nbdof2);
 +      if (mf_u2.is_reduced()) {
 +          gmm::copy(gmm::sub_matrix(mf_u2.reduction_matrix(),
 +                                    gmm::sub_interval(0, nbdof2), SUBI),
 +                    Rsub);
 +          gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
 +                                    SUBI, gmm::sub_interval(0, nbdof2)),
 +                    Esub);
 +      }
++=======
+       size_type nbsub = mf_u2_proj.nb_basic_dof();
+ 
+       std::vector<size_type> ind;
+       mf_u2_proj.get_global_dof_index(ind);
+       gmm::unsorted_sub_index SUBI(ind);
+ 
+       gmm::csc_matrix<scalar_type> Esub(nbsub, nbdof2);
+       if (mf_u2.is_reduced())
+           gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
+                                     SUBI, gmm::sub_interval(0, nbdof2)),
+                     Esub);
++>>>>>>> upstream
  
        model_real_plain_vector u2_proj(nbsub);
        if (mf_u2.is_reduced())
@@@ -1695,54 -1741,72 +2261,119 @@@
        else
          gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
  
++<<<<<<< HEAD
 +      size_type U1L = 0;
 +      size_type LU1 = U1L + (is_symmetric() ? 0 : 1);
 +      size_type U2L = LU1 + 1;
 +      size_type LU2 = U2L + (is_symmetric() ? 0 : 1);
 +      size_type LL  = LU2 + 1;
 +      size_type U1U1 = (option == 1 || option == 3) ? U1L : LL + 1;
 +      size_type U2U2 = (option == 1 || option == 3) ? U2L : LL + 2;
 +      size_type U1U2 = (option == 1 || option == 3) ? U1L : LL + 3;
++=======
+       model_real_plain_vector WT2_proj(0);
+       if (WT2) {
+         gmm::resize(WT2_proj, nbsub);
+         if (mf_u2.is_reduced())
+           gmm::mult(Esub, *WT2, WT2_proj);
+         else
+           gmm::copy(gmm::sub_vector(*WT2, SUBI), WT2_proj);
+       }
+ 
+       size_type U1L = 0;
+       size_type LU1 = is_symmetric() ? size_type(-1) : 1;
+       size_type U2L = is_symmetric() ? 1 : 2;
+       size_type LU2 = is_symmetric() ? size_type(-1) : 3;
+       size_type LL = is_symmetric() ? 2 : 4;
+       size_type U1U1 = (option != 2) ? size_type(-1) : (is_symmetric() ? 3 : 5);
+       size_type U2U2 = (option != 2) ? size_type(-1) : (is_symmetric() ? 4 : 6);
+       size_type U1U2 = (option != 2) ? size_type(-1) : (is_symmetric() ? 5 : 7);
+       size_type U2U1 = (option != 2 || is_symmetric()) ? size_type(-1) : 8;
++>>>>>>> upstream
  
        if (version & model::BUILD_MATRIX) {
          GMM_TRACE2("Integral contact between nonmatching meshes "
                     "tangent term");
          for (size_type i = 0; i < matl.size(); i++) gmm::clear(matl[i]);
  
++<<<<<<< HEAD
++=======
+         model_real_sparse_matrix dummy_mat(0, 0);
+         model_real_sparse_matrix &Klu1 = (LU1 == size_type(-1)) ? dummy_mat : matl[LU1];
+         model_real_sparse_matrix &Ku1u1 = (U1U1 == size_type(-1)) ? dummy_mat : matl[U1U1];
+ 
++>>>>>>> upstream
          model_real_sparse_matrix Ku2l(nbsub, nbdof_lambda);
          model_real_sparse_matrix Klu2(nbdof_lambda, nbsub);
          model_real_sparse_matrix Ku2u2(nbsub, nbsub);
          model_real_sparse_matrix Ku1u2(nbdof1, nbsub);
++<<<<<<< HEAD
 +
 +        if (contact_only)
 +          asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
 +            (matl[U1L], matl[LU1], Ku2l, Klu2, matl[LL], matl[U1U1], Ku2u2, Ku1u2,
 +             mim, mf_u1, u1, *pmf_u2_proj, u2_proj, mf_lambda, lambda,
 +             vr[0], rg, option);
 +        else
 +          asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
 +            (matl[U1L], matl[LU1], Ku2l, Klu2, matl[LL], matl[U1U1], Ku2u2, Ku1u2,
 +             mim, mf_u1, u1, *pmf_u2_proj, u2_proj, mf_lambda, lambda,
 +             pmf_coeff, f_coeff, vr[0], alpha, WT1, WT2, rg, option);
 +
 +        if (mf_u2.is_reduced()) {
 +          gmm::mult(Rsub, Ku2l, matl[U2L]);
 +          if (LU2 != U2L) gmm::mult(Klu2, Esub, matl[LU2]);
 +          if (U2U2 != U2L) {
 +            model_real_sparse_matrix tmp(nbsub, nbdof2);
 +            gmm::mult(Ku2u2, Esub, tmp);
 +            gmm::mult(Rsub, tmp, matl[U2U2]);
 +            gmm::mult(Ku1u2, Esub, matl[U1U2]);
 +          }
 +        }
 +        else {
 +          gmm::copy(Ku2l, gmm::sub_matrix(matl[U2L], SUBI, gmm::sub_interval(0, nbdof_lambda)));
 +          if (LU2 != U2L)
 +            gmm::copy(Klu2, gmm::sub_matrix(matl[LU2], gmm::sub_interval(0, nbdof_lambda), SUBI));
 +          if (U2U2 != U2L) {
 +            gmm::copy(Ku2u2, gmm::sub_matrix(matl[U2U2], SUBI));
 +            gmm::copy(Ku1u2, gmm::sub_matrix(matl[U1U2], gmm::sub_interval(0, nbdof1), SUBI));
 +          }
++=======
+         model_real_sparse_matrix Ku2u1(nbsub, nbdof1);
+ 
+         if (contact_only)
+           asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
+             (matl[U1L], Klu1, Ku2l, Klu2, matl[LL], Ku1u1, Ku2u2, Ku1u2,
+              mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
+              vr[0], rg, option);
+         else
+           asm_Alart_Curnier_contact_nonmatching_meshes_tangent_matrix
+             (matl[U1L], Klu1, Ku2l, Klu2, matl[LL], Ku1u1, Ku2u2, Ku1u2, Ku2u1,
+              mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
+              pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
+ 
+         if (mf_u2.is_reduced()) {
+           gmm::mult(gmm::transposed(Esub), Ku2l, matl[U2L]);
+           if (LU2 != size_type(-1)) gmm::mult(Klu2, Esub, matl[LU2]);
+           if (U2U2 != size_type(-1)) {
+             model_real_sparse_matrix tmp(nbsub, nbdof2);
+             gmm::mult(Ku2u2, Esub, tmp);
+             gmm::mult(gmm::transposed(Esub), tmp, matl[U2U2]);
+           }
+           if (U1U2 != size_type(-1)) gmm::mult(Ku1u2, Esub, matl[U1U2]);
+           if (U2U1 != size_type(-1)) gmm::mult(gmm::transposed(Esub), Ku2u1, matl[U2U1]);
+         }
+         else {
+           gmm::copy(Ku2l, gmm::sub_matrix(matl[U2L], SUBI, gmm::sub_interval(0, nbdof_lambda)));
+           if (LU2 != size_type(-1))
+             gmm::copy(Klu2, gmm::sub_matrix(matl[LU2], gmm::sub_interval(0, nbdof_lambda), SUBI));
+           if (U2U2 != size_type(-1))
+             gmm::copy(Ku2u2, gmm::sub_matrix(matl[U2U2], SUBI));
+           if (U1U2 != size_type(-1))
+             gmm::copy(Ku1u2, gmm::sub_matrix(matl[U1U2], gmm::sub_interval(0, nbdof1), SUBI));
+           if (U2U1 != size_type(-1))
+             gmm::copy(Ku2u1, gmm::sub_matrix(matl[U2U1], SUBI, gmm::sub_interval(0, nbdof1)));
++>>>>>>> upstream
          }
        }
  
@@@ -1754,28 -1818,26 +2385,49 @@@
          if (contact_only)
            asm_Alart_Curnier_contact_nonmatching_meshes_rhs
              (vecl[U1L], Ru2, vecl[LL], // u1, u2, lambda
++<<<<<<< HEAD
 +             mim, mf_u1, u1, *pmf_u2_proj, u2_proj, mf_lambda, lambda,
++=======
+              mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
++>>>>>>> upstream
               vr[0], rg, option);
          else
            asm_Alart_Curnier_contact_nonmatching_meshes_rhs
              (vecl[U1L], Ru2, vecl[LL], // u1, u2, lambda
++<<<<<<< HEAD
 +             mim, mf_u1, u1, *pmf_u2_proj, u2_proj, mf_lambda, lambda,
 +             pmf_coeff, f_coeff, vr[0], alpha, WT1, WT2, rg, option);
 +
 +        if (mf_u2.is_reduced())
 +          gmm::mult(Rsub, Ru2, vecl[U2L]);
 +        else
 +          gmm::copy(Ru2, gmm::sub_vector(vecl[U2L], SUBI));
 +      }
 +
++=======
+              mim, mf_u1, u1, mf_u2_proj, u2_proj, mf_lambda, lambda,
+              pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
+ 
+         if (mf_u2.is_reduced())
+           gmm::mult(gmm::transposed(Esub), Ru2, vecl[U2L]);
+         else
+           gmm::copy(Ru2, gmm::sub_vector(vecl[U2L], SUBI));
+       }
++>>>>>>> upstream
      }
  
      integral_contact_nonmatching_meshes_brick(size_type rg1_, size_type rg2_,
                                                  bool contact_only_, int option_)
++<<<<<<< HEAD
 +    : rg1(rg1_), rg2(rg2_), pfem_proj(0), pmf_u2_proj(0),
 +      contact_only(contact_only_), option(option_)
 +    {
 +      Tresca_version = false;   // for future version ...
++=======
+     : rg1(rg1_), rg2(rg2_), pfem_proj(0),
+       contact_only(contact_only_), option(option_)
+     {
++>>>>>>> upstream
        set_flags(contact_only
                  ? "Integral contact between nonmatching meshes brick"
                  : "Integral contact and friction between nonmatching "
@@@ -1787,7 -1849,7 +2439,11 @@@
      }
  
      ~integral_contact_nonmatching_meshes_brick()
++<<<<<<< HEAD
 +    { if (pmf_u2_proj) delete pmf_u2_proj; }
++=======
+     { if (pfem_proj) del_projected_fem(pfem_proj); }
++>>>>>>> upstream
  
    };
  
@@@ -1846,7 -1908,7 +2502,11 @@@
    size_type add_integral_contact_between_nonmatching_meshes_brick
    (model &md, const mesh_im &mim, const std::string &varname_u1,
     const std::string &varname_u2, const std::string &multname,
++<<<<<<< HEAD
 +   const std::string &dataname_r, const std::string &dataname_friction_coeff,
++=======
+    const std::string &dataname_r, const std::string &dataname_friction_coeffs,
++>>>>>>> upstream
     size_type region1, size_type region2, int option,
     const std::string &dataname_alpha,
     const std::string &dataname_wt1, const std::string &dataname_wt2) {
@@@ -1879,14 -1941,14 +2539,25 @@@
                            "Incorrect option for integral contact brick");
      }
  
++<<<<<<< HEAD
 +    model::varnamelist dl(1, dataname_r);  // 0 -> r
 +    dl.push_back(dataname_friction_coeff); // 1 -> f_coeff
 +    if (dataname_alpha.size()) {
 +      dl.push_back(dataname_alpha);        // 2 -> alpha
 +      if (dataname_wt1.size()) {
 +        dl.push_back(dataname_wt1);        // 3 -> WT1
 +        if (dataname_wt2.size()) {
 +          dl.push_back(dataname_wt2);      // 4 -> WT2
++=======
+     model::varnamelist dl(1, dataname_r);   // 0 -> r
+     dl.push_back(dataname_friction_coeffs); // 1 -> f_coeff,[tau_adh,tresca_lim]
+     if (dataname_alpha.size()) {
+       dl.push_back(dataname_alpha);         // 2 -> alpha
+       if (dataname_wt1.size()) {
+         dl.push_back(dataname_wt1);         // 3 -> WT1
+         if (dataname_wt2.size()) {
+           dl.push_back(dataname_wt2);       // 4 -> WT2
++>>>>>>> upstream
            // TODO: VT1, VT2, gamma
          }
        }
@@@ -1977,7 -2039,7 +2648,11 @@@
     const getfem::mesh_fem &mf_u1, const VECT1 &U1,
     const getfem::mesh_fem &mf_u2, const VECT1 &U2,
     const getfem::mesh_fem *pmf_lambda, const VECT1 *lambda,
++<<<<<<< HEAD
 +   const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeff, scalar_type r,
++=======
+    const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeffs, scalar_type r,
++>>>>>>> upstream
     scalar_type alpha, const VECT1 *WT1, const VECT1 *WT2,
     const mesh_region &rg, int option = 1) {
  
@@@ -1990,7 -2052,7 +2665,11 @@@
  
      contact_nonmatching_meshes_nonlinear_term
        nterm(subterm, r, mf_u1, U1, mf_u2, U2, pmf_lambda, lambda,
++<<<<<<< HEAD
 +            pmf_coeff, f_coeff, alpha, WT1, WT2);
++=======
+             pmf_coeff, f_coeffs, alpha, WT1, WT2);
++>>>>>>> upstream
  
      const std::string aux_fems = pmf_coeff ? "#1,#2,#3,#4"
                                             : (pmf_lambda ? "#1,#2,#3": "#1,#2");
@@@ -2031,7 -2093,7 +2710,11 @@@
     const getfem::mesh_fem &mf_u1, const VECT1 &U1,
     const getfem::mesh_fem &mf_u2, const VECT1 &U2,
     const getfem::mesh_fem *pmf_lambda, const VECT1 *lambda,
++<<<<<<< HEAD
 +   const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeff, scalar_type r,
++=======
+    const getfem::mesh_fem *pmf_coeff, const VECT1 *f_coeffs, scalar_type r,
++>>>>>>> upstream
     scalar_type alpha, const VECT1 *WT1, const VECT1 *WT2,
     const mesh_region &rg, int option = 1) {
  
@@@ -2044,7 -2106,7 +2727,11 @@@
  
      contact_nonmatching_meshes_nonlinear_term
        nterm(subterm, r, mf_u1, U1, mf_u2, U2, pmf_lambda, lambda,
++<<<<<<< HEAD
 +            pmf_coeff, f_coeff, alpha, WT1, WT2);
++=======
+             pmf_coeff, f_coeffs, alpha, WT1, WT2);
++>>>>>>> upstream
  
      const std::string aux_fems = pmf_coeff ? "#1,#2,#3,#4"
                                             : (pmf_lambda ? "#1,#2,#3": "#1,#2");
@@@ -2077,9 -2139,8 +2764,14 @@@
  
      size_type rg1, rg2; // ids of mesh regions on mf_u1 and mf_u2 that are
                          // expected to come in contact.
++<<<<<<< HEAD
 +    mutable getfem::pfem pfem_proj;        // cached fem and mesh_fem for the
 +    mutable getfem::mesh_fem *pmf_u2_proj; // projection between nonmatching meshes
 +    bool Tresca_version, contact_only;
++=======
+     mutable getfem::pfem pfem_proj; // cached fem for the projection between nonmatching meshes
+     bool contact_only;
++>>>>>>> upstream
      int option;
  
      virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
@@@ -2106,7 -2167,7 +2798,11 @@@
  
        size_type N = mf_u1.linked_mesh().dim();
  
++<<<<<<< HEAD
 +      // Data : r, [lambda,] [friction_coeff,] [alpha,] [WT1, WT2]
++=======
+       // Data : r, [lambda,] [friction_coeffs,] [alpha,] [WT1, WT2]
++>>>>>>> upstream
        size_type nb_data_1 = ((option == 1) ? 1 : 2) + (contact_only ? 0 : 1);
        size_type nb_data_2 = nb_data_1 + (contact_only ? 0 : 3);
        GMM_ASSERT1(dl.size() >= nb_data_1 && dl.size() <= nb_data_2,
@@@ -2131,36 -2192,42 +2827,69 @@@
                      "has not the right format");
        }
  
++<<<<<<< HEAD
 +      const model_real_plain_vector *f_coeff = 0;
++=======
+       const model_real_plain_vector *f_coeffs = 0;
++>>>>>>> upstream
        const mesh_fem *pmf_coeff = 0;
        scalar_type alpha = 1;
        const model_real_plain_vector *WT1 = 0;
        const model_real_plain_vector *WT2 = 0;
        if (!contact_only) {
          nd++;
++<<<<<<< HEAD
 +        f_coeff = &(md.real_variable(dl[nd]));
 +        pmf_coeff = md.pmesh_fem_of_variable(dl[nd]);
 +        sl = gmm::vect_size(*f_coeff);
 +        if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
 +        GMM_ASSERT1(sl == 1,
 +                  "the data corresponding to the friction coefficient "
 +                  "has not the right format");
 +
 +        if (dl.size() > nd) {
++=======
+         f_coeffs = &(md.real_variable(dl[nd]));
+         pmf_coeff = md.pmesh_fem_of_variable(dl[nd]);
+         sl = gmm::vect_size(*f_coeffs);
+         if (pmf_coeff) { sl *= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
+         GMM_ASSERT1(sl == 1 || sl == 2 || sl == 3,
+                   "the data corresponding to the friction coefficient "
+                   "has not the right format");
+ 
+         if (dl.size() > nd+1) {
++>>>>>>> upstream
            nd++;
            alpha = md.real_variable(dl[nd])[0];
            GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[nd])) == 1,
                        "Parameter alpha should be a scalar");
          }
  
++<<<<<<< HEAD
 +        if (dl.size() > nd) {
 +          nd++;
 +          WT1 = &(md.real_variable(dl[nd]));
 +        }
 +
 +        if (dl.size() > nd) {
 +          nd++;
 +          WT2 = &(md.real_variable(dl[nd]));
++=======
+         if (dl.size() > nd+1) {
+           nd++;
+           if (dl[nd].compare(vl[0]) != 0)
+             WT1 = &(md.real_variable(dl[nd]));
+           else if (md.n_iter_of_variable(vl[0]) > 1)
+             WT1 = &(md.real_variable(vl[0],1));
+         }
+ 
+         if (dl.size() > nd+1) {
+           nd++;
+           if (dl[nd].compare(vl[1]) != 0)
+             WT2 = &(md.real_variable(dl[nd]));
+           else if (md.n_iter_of_variable(vl[1]) > 1)
+             WT2 = &(md.real_variable(vl[1],1));
++>>>>>>> upstream
          }
        }
  
@@@ -2172,29 -2239,25 +2901,51 @@@
        mf_u1.linked_mesh().intersect_with_mpi_region(rg); // FIXME: mfu_2?
  
        // projection of the second mesh_fem onto the mesh of the first mesh_fem
++<<<<<<< HEAD
 +      if (!pmf_u2_proj) {
 +        pmf_u2_proj = new getfem::mesh_fem(mim.linked_mesh(), dim_type(N));
 +        pfem_proj = new_projected_fem(mf_u2, mim, rg2, rg1);
 +        pmf_u2_proj->set_finite_element(mim.linked_mesh().convex_index(), pfem_proj);
 +      }
 +
 +      size_type nbdof1 = mf_u1.nb_dof();
 +      size_type nbdof2 = mf_u2.nb_dof();
 +      size_type nbsub = pmf_u2_proj->nb_dof();
 +
 +      std::vector<size_type> ind;
 +      pmf_u2_proj->get_global_dof_index(ind);
 +      gmm::unsorted_sub_index SUBI(ind);
 +
 +      gmm::csc_matrix<scalar_type> Rsub(nbdof2, nbsub), Esub(nbsub, nbdof2);
 +      if (mf_u2.is_reduced()) {
 +          gmm::copy(gmm::sub_matrix(mf_u2.reduction_matrix(),
 +                                    gmm::sub_interval(0, nbdof2), SUBI),
 +                    Rsub);
 +          gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
 +                                    SUBI, gmm::sub_interval(0, nbdof2)),
 +                    Esub);
 +      }
++=======
+       if (!pfem_proj)
+         pfem_proj = new_projected_fem(mf_u2, mim, rg2, rg1);
+ 
+       getfem::mesh_fem mf_u2_proj(mim.linked_mesh(), dim_type(N));
+       mf_u2_proj.set_finite_element(mim.linked_mesh().convex_index(), pfem_proj);
+ 
+       size_type nbdof1 = mf_u1.nb_dof();
+       size_type nbdof2 = mf_u2.nb_dof();
+       size_type nbsub = mf_u2_proj.nb_dof();
+ 
+       std::vector<size_type> ind;
+       mf_u2_proj.get_global_dof_index(ind);
+       gmm::unsorted_sub_index SUBI(ind);
+ 
+       gmm::csc_matrix<scalar_type> Esub(nbsub, nbdof2);
+       if (mf_u2.is_reduced())
+           gmm::copy(gmm::sub_matrix(mf_u2.extension_matrix(),
+                                     SUBI, gmm::sub_interval(0, nbdof2)),
+                     Esub);
++>>>>>>> upstream
  
        model_real_plain_vector u2_proj(nbsub);
        if (mf_u2.is_reduced())
@@@ -2202,6 -2265,15 +2953,18 @@@
        else
          gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
  
++<<<<<<< HEAD
++=======
+       model_real_plain_vector WT2_proj(0);
+       if (WT2) {
+         gmm::resize(WT2_proj, nbsub);
+         if (mf_u2.is_reduced())
+           gmm::mult(Esub, *WT2, WT2_proj);
+         else
+           gmm::copy(gmm::sub_vector(*WT2, SUBI), WT2_proj);
+       }
+ 
++>>>>>>> upstream
        if (version & model::BUILD_MATRIX) {
          GMM_TRACE2("Penalized contact between nonmatching meshes tangent term");
          gmm::clear(matl[0]);
@@@ -2213,22 -2285,25 +2976,39 @@@
  
          if (contact_only) {
            asm_penalized_contact_nonmatching_meshes_tangent_matrix
++<<<<<<< HEAD
 +            (matl[0], Ku2u2, Ku1u2, mim, mf_u1, u1, *pmf_u2_proj, u2_proj,
++=======
+             (matl[0], Ku2u2, Ku1u2, mim, mf_u1, u1, mf_u2_proj, u2_proj,
++>>>>>>> upstream
               pmf_lambda, lambda, vr[0], rg, option);
          }
          else {
            gmm::clear(matl[3]);
            model_real_sparse_matrix Ku2u1(nbsub,nbdof1);
            asm_penalized_contact_nonmatching_meshes_tangent_matrix
++<<<<<<< HEAD
 +            (matl[0], Ku2u2, Ku1u2, Ku2u1, mim, mf_u1, u1, *pmf_u2_proj, u2_proj,
 +             pmf_lambda, lambda, pmf_coeff, f_coeff, vr[0], alpha, WT1, WT1, rg, option);
 +          gmm::copy(Ku2u1, gmm::sub_matrix(matl[3], SUBI, gmm::sub_interval(0, nbdof1)));
++=======
+             (matl[0], Ku2u2, Ku1u2, Ku2u1, mim, mf_u1, u1, mf_u2_proj, u2_proj,
+              pmf_lambda, lambda, pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
+           if (mf_u2.is_reduced())
+             gmm::mult(gmm::transposed(Esub), Ku2u1, matl[3]);
+           else
+             gmm::copy(Ku2u1, gmm::sub_matrix(matl[3], SUBI, gmm::sub_interval(0, nbdof1)));
++>>>>>>> upstream
          }
  
          if (mf_u2.is_reduced()) {
            model_real_sparse_matrix tmp(nbsub, nbdof2);
            gmm::mult(Ku2u2, Esub, tmp);
++<<<<<<< HEAD
 +          gmm::mult(Rsub, tmp, matl[1]);
++=======
+           gmm::mult(gmm::transposed(Esub), tmp, matl[1]);
++>>>>>>> upstream
            gmm::mult(Ku1u2, Esub, matl[2]);
          }
          else {
@@@ -2245,15 -2320,15 +3025,27 @@@
  
          if (contact_only)
            asm_penalized_contact_nonmatching_meshes_rhs
++<<<<<<< HEAD
 +            (vecl[0], Ru2, mim, mf_u1, u1, *pmf_u2_proj, u2_proj, pmf_lambda, lambda,
 +             vr[0], rg, option);
 +        else
 +          asm_penalized_contact_nonmatching_meshes_rhs
 +            (vecl[0], Ru2, mim, mf_u1, u1, *pmf_u2_proj, u2_proj, pmf_lambda, lambda,
 +             pmf_coeff, f_coeff, vr[0], alpha, WT1, WT2, rg, option);
 +
 +        if (mf_u2.is_reduced())
 +          gmm::mult(Rsub, Ru2, vecl[1]);
++=======
+             (vecl[0], Ru2, mim, mf_u1, u1, mf_u2_proj, u2_proj, pmf_lambda, lambda,
+              vr[0], rg, option);
+         else
+           asm_penalized_contact_nonmatching_meshes_rhs
+             (vecl[0], Ru2, mim, mf_u1, u1, mf_u2_proj, u2_proj, pmf_lambda, lambda,
+              pmf_coeff, f_coeffs, vr[0], alpha, WT1, &WT2_proj, rg, option);
+ 
+         if (mf_u2.is_reduced())
+           gmm::mult(gmm::transposed(Esub), Ru2, vecl[1]);
++>>>>>>> upstream
          else
            gmm::copy(Ru2, gmm::sub_vector(vecl[1], SUBI));
        }
@@@ -2261,9 -2336,9 +3053,15 @@@
  
      penalized_contact_nonmatching_meshes_brick(size_type rg1_, size_type rg2_,
                                                 bool contact_only_, int option_)
++<<<<<<< HEAD
 +    : rg1(rg1_), rg2(rg2_), pfem_proj(0), pmf_u2_proj(0),
 +      contact_only(contact_only_), option(option_) {
 +      Tresca_version = false;   // for future version ...
++=======
+     : rg1(rg1_), rg2(rg2_), pfem_proj(0),
+       contact_only(contact_only_), option(option_)
+     {
++>>>>>>> upstream
        set_flags(contact_only
                  ? "Integral penalized contact between nonmatching meshes brick"
                  : "Integral penalized contact and friction between nonmatching "
@@@ -2274,7 -2349,7 +3072,11 @@@
      }
  
      ~penalized_contact_nonmatching_meshes_brick()
++<<<<<<< HEAD
 +    { if (pmf_u2_proj) delete pmf_u2_proj; }
++=======
+     { if (pfem_proj) del_projected_fem(pfem_proj); }
++>>>>>>> upstream
  
    };
  
@@@ -2319,7 -2394,7 +3121,11 @@@
    size_type add_penalized_contact_between_nonmatching_meshes_brick
    (model &md, const mesh_im &mim, const std::string &varname_u1,
     const std::string &varname_u2, const std::string &dataname_r,
++<<<<<<< HEAD
 +   const std::string &dataname_friction_coeff,
++=======
+    const std::string &dataname_friction_coeffs,
++>>>>>>> upstream
     size_type region1, size_type region2, int option,
     const std::string &dataname_lambda, const std::string &dataname_alpha,
     const std::string &dataname_wt1, const std::string &dataname_wt2) {
@@@ -2338,7 -2413,7 +3144,11 @@@
      case 2: case 3: dl.push_back(dataname_lambda); break;
      default: GMM_ASSERT1(false, "Penalized contact brick : invalid option");
      }
++<<<<<<< HEAD
 +    dl.push_back(dataname_friction_coeff);
++=======
+     dl.push_back(dataname_friction_coeffs);
++>>>>>>> upstream
      if (dataname_alpha.size() > 0) {
        dl.push_back(dataname_alpha);
        if (dataname_wt1.size() > 0) {
@@@ -2384,7 -2459,9 +3194,13 @@@
        const model_real_plain_vector &obs = md.real_variable(dl[0]);
        const mesh_fem &mf_obs = md.mesh_fem_of_variable(dl[0]);
  
++<<<<<<< HEAD
 +      area = asm_level_set_contact_area(*ml[0], mf_u, u, mf_obs, obs, reg, -1e-3);
++=======
+       //FIXME: use an adapted integration method
+       area = asm_level_set_contact_area(*ml[0], mf_u, u, mf_obs, obs, reg, -1e-3,
+                                         &mf_lambda, &lambda, 1e-1);
++>>>>>>> upstream
  
        gmm::resize(F, mf_u.nb_dof());
        asm_level_set_normal_source_term
@@@ -2397,6 -2474,7 +3213,10 @@@
          = dynamic_cast<penalized_contact_rigid_obstacle_brick *>
           (const_cast<virtual_brick *>(pbr.get()));
        GMM_ASSERT1(p, "Wrong type of brick");
++<<<<<<< HEAD
++=======
+       GMM_ASSERT1(false, "Not implemented yet");
++>>>>>>> upstream
      }
      else if (pbr->brick_name() == "Integral contact between nonmatching meshes brick" ||
               pbr->brick_name() == "Integral contact and friction between nonmatching "
@@@ -2414,12 -2492,16 +3234,25 @@@
        const model_real_plain_vector &lambda = md.real_variable(vl[2]);
        const mesh_fem &mf_lambda = md.mesh_fem_of_variable(vl[2]);
  
++<<<<<<< HEAD
 +      std::vector<size_type> ind;
 +      p->pmf_u2_proj->get_global_dof_index(ind);
 +      gmm::unsorted_sub_index SUBI(ind);
 +
 +      size_type nbdof2 = mf_u2.nb_dof();
 +      size_type nbsub = p->pmf_u2_proj->nb_basic_dof();
++=======
+       getfem::pfem pfem_proj = new_projected_fem(mf_u2, *ml[0], p->rg2, p->rg1);
+       getfem::mesh_fem mf_u2_proj(mf_u1.linked_mesh(), mf_u1.linked_mesh().dim());
+       mf_u2_proj.set_finite_element(mf_u1.linked_mesh().convex_index(), pfem_proj);
+ 
+       std::vector<size_type> ind;
+       mf_u2_proj.get_global_dof_index(ind);
+       gmm::unsorted_sub_index SUBI(ind);
+ 
+       size_type nbdof2 = mf_u2.nb_dof();
+       size_type nbsub = mf_u2_proj.nb_basic_dof();
++>>>>>>> upstream
        model_real_plain_vector u2_proj(nbsub);
  
        if (mf_u2.is_reduced()) {
@@@ -2432,13 -2514,16 +3265,26 @@@
        else
          gmm::copy(gmm::sub_vector(u2, SUBI), u2_proj);
  
++<<<<<<< HEAD
 +      area = asm_nonmatching_meshes_contact_area
 +             (*ml[0], mf_u1, u1, *(p->pmf_u2_proj), u2_proj, reg, -1e-3);
 +
 +      gmm::resize(F, mf_u1.nb_dof());
 +      asm_nonmatching_meshes_normal_source_term
 +        (F, *ml[0], mf_u1, *(p->pmf_u2_proj), mf_lambda, lambda, reg);
 +
++=======
+       //FIXME: use an adapted integration method
+       area = asm_nonmatching_meshes_contact_area
+              (*ml[0], mf_u1, u1, mf_u2_proj, u2_proj, reg, -1e-3,
+               &mf_lambda, &lambda, 1e-1);
+ 
+       gmm::resize(F, mf_u1.nb_dof());
+       asm_nonmatching_meshes_normal_source_term
+         (F, *ml[0], mf_u1, mf_u2_proj, mf_lambda, lambda, reg);
+ 
+       del_projected_fem(pfem_proj);
++>>>>>>> upstream
      }
      else if (pbr->brick_name() == "Integral penalized contact between nonmatching meshes brick" ||
               pbr->brick_name() == "Integral penalized contact and friction between nonmatching "
@@@ -2447,70 -2532,99 +3293,165 @@@
          = dynamic_cast<penalized_contact_nonmatching_meshes_brick *>
           (const_cast<virtual_brick *>(pbr.get()));
        GMM_ASSERT1(p, "Wrong type of brick");
++<<<<<<< HEAD
++=======
+       GMM_ASSERT1(false, "Not implemented yet");
++>>>>>>> upstream
      }
  
    }
  
++<<<<<<< HEAD
 +
 +
 +#ifdef EXPERIMENTAL_PURPOSE_ONLY
 +
 +
 +  // Experimental implementation of contact condition with Nitsche method.
 +  // To be deleted when a more general implementation will be designed.
 +
 +
 +  class contact_nitsche_nonlinear_term : public nonlinear_elem_term {
 +
 +  protected:
 +    base_small_vector lnt, lt; // multiplier lambda and its tangential component lambda_t
 +    scalar_type ln;            // normal component lambda_n of the multiplier
 +    base_small_vector ut;      // tangential relative displacement
 +    scalar_type un;            // normal relative displacement (positive when the first
 +                               // elastic body surface moves outwards)
 +    base_small_vector no, n;   // surface normal, pointing outwards with respect
 +                               // to the (first) elastic body
 +    scalar_type g, f_coeff;    // gap and coefficient of friction values
 +    scalar_type lambda, mu;    // Lame coefficients
 +
 +    base_small_vector aux1, auxN, V;
 +    base_matrix GP, grad;
 +    base_vector coeff;
 +    const mesh_fem &mf_u;       // mandatory
 +    const mesh_fem &mf_obs;     // mandatory
 +    const mesh_fem *pmf_coeff;
 +    base_vector U, obs, friction_coeff;
 +
 +    void adjust_tensor_size(void) {
 +      sizes_.resize(4); sizes_[0] = sizes_[1] = sizes_[2] = sizes_[3] = N;
 +      switch (option) {
 +      case 1 : sizes_.resize(1); break;
 +      case 2 : case 3 :  sizes_.resize(2); break;
 +      case 4 : case 5 :  sizes_.resize(3); break;
 +      }
 +      gmm::resize(grad, 1, N);
 +      lnt.resize(N); lt.resize(N); ut.resize(N); no.resize(N); n.resize(N);
 +      aux1.resize(1); auxN.resize(N); V.resize(N);
 +      gmm::resize(GP, N, N);
 +    }
 +
 +  public:
 +    dim_type N;
 +    size_type option;
 +    scalar_type r;
 +
 +    bgeot::multi_index sizes_;
 +
 +    template <typename VECT1>
 +    contact_nitsche_nonlinear_term(size_type option_, scalar_type r_,
 +				   scalar_type lambda_, scalar_type mu_,
 +				   const mesh_fem &mf_u_, const VECT1 &U_,
 +				   const mesh_fem &mf_obs_, const VECT1 &obs_,
 +				   const mesh_fem *pmf_coeff_ = 0,
 +				   const VECT1 *f_coeff_ = 0)		  
 +      : lambda(lambda_), mu(mu_), mf_u(mf_u_),
 +      mf_obs(mf_obs_), pmf_coeff(pmf_coeff_), U(mf_u.nb_basic_dof()),
 +	obs(mf_obs.nb_basic_dof()), friction_coeff(0), option(option_), r(r_) {
++=======
+   //=========================================================================
+   //
+   //  Contact condition with a rigid obstacle : generic Nitsche's method
+   //
+   //=========================================================================
+ 
+ 
+   class contact_nitsche_nonlinear_term : public nonlinear_elem_term {
+     // Option:
+     // 1 : rhs term
+     // 2 : tangent term in main unknown (u)
+     // 3 : tangent term in auxilliary variable (p)
+ 
+   protected:
+     base_small_vector u;      // tangential relative displacement
+     scalar_type un;            // normal relative displacement (positive when
+                                //  the first elas. body surface moves outwards)
+     base_small_vector no, n;   // surface normal, pointing outwards with
+                                // respect to the (first) elastic body
+     scalar_type g, f_coeff;    // gap and friction coefficient
+ 
+     base_small_vector aux1, wt, V, Pr, pgg, zeta;
+     base_matrix GPr, grad;
+     base_vector coeff;
+     const model *md;
+     const std::string *varname;
+     const std::string *auxvarname;
+     const mesh_fem &mf_u;       // mandatory
+     const mesh_fem &mf_obs;     // mandatory
+     const mesh_fem *pmf_coeff;
+     const mesh_fem *mf_p;
+     base_vector U, obs, friction_coeff, WT;
+     dim_type N;
+     size_type option;
+     scalar_type gamma, gamma0, theta, alpha;
+     base_tensor tG, tp, tpp, tbv, tpaux;
+     mutable bgeot::multi_index sizes_;
+ 
+     void adjust_tensor_size(void) {
+       sizes_.resize(1); sizes_[0] = N;
+       tG.adjust_sizes(sizes_);
+       sizes_.resize(2); sizes_[0] = sizes_[1] = 1;
+       switch (option) {
+       case 1 : sizes_.resize(1); break;
+       case 2 : case 3 :  break;
+       }
+       gmm::resize(grad, 1, N);
+       u.resize(N); no.resize(N); n.resize(N);
+       aux1.resize(1); wt.resize(N); V.resize(N); zeta.resize(N);
+       gmm::resize(GPr, N, N); gmm::resize(Pr, N); gmm::resize(pgg, N);
+     }
+ 
+   public:
+     const bgeot::multi_index &sizes(size_type cv) const {
+       if (cv != size_type(-1))
+         switch(option) {
+         case 1:
+           sizes_[0] = short_type(mf_u.nb_basic_dof_of_element(cv));
+           break;
+         case 2:
+           sizes_[0] = sizes_[1]= short_type(mf_u.nb_basic_dof_of_element(cv));
+           break;
+         case 3:
+           sizes_[0] = short_type(mf_u.nb_basic_dof_of_element(cv));
+           sizes_[1] = short_type(mf_p->nb_basic_dof_of_element(cv));
+           break;
+         }
+       return sizes_;
+     }
+ 
+ 
+     contact_nitsche_nonlinear_term
+       (size_type option_, scalar_type gamma0_, scalar_type theta_,
+        scalar_type alpha_, const model &md_, const std::string &varname_,
+        const mesh_fem &mf_u_, const model_real_plain_vector &U_,
+        const mesh_fem &mf_obs_,
+        const model_real_plain_vector &obs_,
+        const std::string &auxvarname_,
+        const mesh_fem *pmf_p_ = 0,
+        const mesh_fem *pmf_coeff_ = 0,
+        const model_real_plain_vector *f_coeff_ = 0,
+        const model_real_plain_vector *WT_ = 0)
+       : md(&md_), varname(&varname_), auxvarname(&auxvarname_),
+         mf_u(mf_u_), mf_obs(mf_obs_),
+         pmf_coeff(pmf_coeff_), mf_p(pmf_p_), U(mf_u.nb_basic_dof()),
+         obs(mf_obs.nb_basic_dof()),
+         friction_coeff(0), option(option_),
+         gamma0(gamma0_), theta(theta_), alpha(alpha_) {
++>>>>>>> upstream
        N = mf_u_.linked_mesh().dim();
        adjust_tensor_size();
  
@@@ -2518,242 -2632,295 +3459,528 @@@
        mf_obs.extend_vector(obs_, obs);
  
        if (!pmf_coeff)
 -        if (f_coeff_) f_coeff = (*f_coeff_)[0]; else f_coeff = scalar_type(0);
++<<<<<<< HEAD
 +	f_coeff = (*f_coeff_)[0];
        else {
 -        friction_coeff.resize(pmf_coeff->nb_basic_dof());
 -        pmf_coeff->extend_vector(*f_coeff_, friction_coeff);
 -      }
 -      if (WT_) {
 -        WT.resize(mf_u.nb_basic_dof());
 -        mf_u_.extend_vector(*WT_, WT);
 +	friction_coeff.resize(pmf_coeff->nb_basic_dof());
 +	pmf_coeff->extend_vector(*f_coeff_, friction_coeff);
        }
      }
  
 +    const bgeot::multi_index &sizes() const { return sizes_; }
  
 -    void compute(fem_interpolation_context &ctx, bgeot::base_tensor &t) {
 +    virtual void compute(fem_interpolation_context&, bgeot::base_tensor &t);
 +    virtual void prepare(fem_interpolation_context& /*ctx*/, size_type /*nb*/);
  
 -      md->compute_Neumann_terms(1, *varname, mf_u, U, ctx, n, tG);
 -      for (size_type i = 0; i < N; ++i)
 -        zeta[i] = tG[i]
 -          + ((g-un+alpha*un) * no[i] + alpha*wt[i] - alpha*u[i] ) / gamma;
 -      if ((option == 1) || (theta != scalar_type(0))) {
 -        coupled_projection(zeta, no, f_coeff, Pr);
 -        gmm::add(Pr, gmm::scaled(tG.as_vector(), -scalar_type(1)), pgg);
 -      }
 +  };
  
 -      switch (option) {
 -      case 1:
 -        {
 -          ctx.pf()->real_base_value(ctx, tbv);
 -          size_type qmult = N / ctx.pf()->target_dim();
 -          short_type nbdofu = sizes_[0];
 -          if (theta != scalar_type(0)) {
 -            sizes_.resize(2);
 -            sizes_[1] = N;
 -            tp.adjust_sizes(sizes_);
 -            sizes_.resize(1);
 -            md->compute_Neumann_terms(2, *varname, mf_u, U, ctx, n, tp);
 -          }
 -          for (size_type i = 0; i < nbdofu; ++i) {
 -            t[i] = scalar_type(0);
 -            for (size_type j = 0; j < N; ++j) {
 -              if (theta != scalar_type(0))
 -                t[i] -= gamma*pgg[j]*theta*tp(i,j);
 -              if (qmult == 1) t[i] += Pr[j]*tbv(i,j);
 -            }
 -            if (qmult > 1) t[i] += Pr[i%N] * tbv(i/N,0);
 -          }
 -        }
 -        break;
 +  void contact_nitsche_nonlinear_term::compute
 +  (fem_interpolation_context &/* ctx */, bgeot::base_tensor &t) {
  
 -      case 2:
 -        {
 -          short_type nbdofu = sizes_[1];
 -          sizes_[1] = N;
 +    t.adjust_sizes(sizes_);
 +    scalar_type e;
 +    dim_type i, j, k, l;
 +
 +    if (option >= 3) { // computation of matrix A
 +      e = f_coeff*gmm::neg(ln-r*(un-g));
 +      auxN = lt - r*ut;
 +      ball_projection_grad(auxN, e, GP);
 +      ball_projection_grad_r(auxN, e, V);
 +      e = Heav(r*(un-g) - ln);
 +      gmm::rank_one_update(GP, no, gmm::scaled(V, -e*f_coeff));
 +      gmm::rank_one_update(GP, gmm::scaled(no, e-gmm::vect_sp(GP,no,no)), no);
 +      gmm::scale(GP, 1./r);
 +    } else { // computation of vector W
 +      e = gmm::neg(ln-r*(un-g));
 +      V = lt - r*ut;
 +      ball_projection(V, f_coeff*e);
 +      V -= e*no;
 +    }
 +
 +    switch (option) {
 +      // one-dimensional tensors [N]
 +    case 1:
 +      for (i=0; i < N; ++i) t[i] = V[i];
 +      break;
 +
 +      // two-dimensional tensors [N x N]
 +    case 2:
 +      V -= lnt;
 +      gmm::scale(V, -1./r);
 +      e = gmm::vect_sp(V, n);
 +      for (i=0; i < N; ++i)
 +	for (j=0; j < N; ++j) {
 +	  t(i,j) = mu*(V[i]*n[j]+V[j]*n[i]);
 +	  if (i == j) t(i,j) += lambda*e;
 +	}
 +      break;
 +
 +    case 3:
 +      for (i=0; i < N; ++i)
 +	for (j=0; j < N; ++j)
 +	  t(i,j) = r*r*GP(j,i);
 +      break;
 +
 +    // three-dimensional tensors [N x N x N]
 +    case 4:
 +      gmm::mult(gmm::transposed(GP), n, V);
 +      for (i=0; i < N; ++i)
 +	for (j=0; j < N; ++j)
 +	  for (k=0; k < N; ++k) {
 +	    t(i,j,k) = -r*mu*(GP(j,i)*n[k] + GP(k,i)*n[j]);
 +	    if (j == k) t(i,j,k) -= r*lambda*V[i];
 +	  } 
 +      break;
 +       
 +    case 5:
 +      gmm::mult(GP, n, V);
 +      for (i=0; i < N; ++i)
 +	for (j=0; j < N; ++j)
 +	  for (k=0; k < N; ++k) {
 +	    t(i,j,k) = -r*mu*(GP(k,i)*n[j] + GP(k,j)*n[i]);
 +	    if (i == j) t(i,j,k) -= r*lambda*V[k];
 +	  } 
 +      break;
 +      
 +    // four-dimensional tensors [N x N x N x N]
 +
 +    case 6:
 +
 +      for (i=0; i < N; ++i) GP(i,i) -= 1./r;  // matrix B
 +
 +      e = gmm::vect_sp(GP, n, n);
 +      gmm::mult(gmm::transposed(GP), n, auxN);
 +      gmm::mult(GP, n, V);
 +
 +      for (i=0; i < N; ++i)
 +	for (j=0; j < N; ++j)
 +	  for (k=0; k < N; ++k)
 +	    for (l=0; l < N; ++l) {
 +	      t(i,j,k,l) = mu*mu*(n[i]*GP(k,j)*n[l] + n[j]*GP(k,i)*n[l]
 +				  + n[j]*GP(l,i)*n[k] + n[i]*GP(l,j)*n[k]);
 +	      if (i == j && k == l) t(i,j,k,l) += lambda*lambda*e;
 +	      if (i == j) t(i,j,k,l) += lambda*mu*(V[k]*n[l] + V[l]*n[k]);
 +	      if (k == l) t(i,j,k,l) += lambda*mu*(auxN[j]*n[i]+auxN[i]*n[j]);
 +	    }
 +
 +      break;
 +    default : GMM_ASSERT1(false, "Invalid option");
 +    }
 +  }
 +
 +
 +  void contact_nitsche_nonlinear_term::prepare
 +  (fem_interpolation_context& ctx, size_type nb) {
 +    size_type cv = ctx.convex_num();
 +
 +    switch (nb) { // last is computed first
 +    case 1 : // calculate [un] and [ut] interpolating [U] on [mf_u]
 +      coeff.resize(mf_u.nb_basic_dof_of_element(cv));
 +      gmm::copy(gmm::sub_vector(U, gmm::sub_index
 +				(mf_u.ind_basic_dof_of_element(cv))), coeff);
 +      ctx.pf()->interpolation(ctx, coeff, V, N);
 +      un = gmm::vect_sp(V, no);
 +      ut = V - un * no;
 +      ctx.pf()->interpolation_grad(ctx, coeff, GP, N);
 +      lnt = lambda*(gmm::mat_trace(GP))*n;
 +      gmm::mult_add(GP, gmm::scaled(n, mu), lnt);
 +      gmm::mult_add(gmm::transposed(GP), gmm::scaled(n, mu), lnt);      
 +      ln = gmm::vect_sp(lnt, no);
 +      lt = lnt - ln * no;
 +      break;
 +
 +    case 2 : // calculate [g] and [no] interpolating [obs] on [mf_obs]
 +             // calculate [ln] and [lt] from [lnt] and [no]
 +      coeff.resize(mf_obs.nb_basic_dof_of_element(cv));
 +      gmm::copy(gmm::sub_vector
 +                (obs, gmm::sub_index
 +                 (mf_obs.ind_basic_dof_of_element(cv))), coeff);
 +      ctx.pf()->interpolation_grad(ctx, coeff, grad, 1);
 +      gmm::copy(gmm::mat_row(grad, 0), no);
 +      no /= -gmm::vect_norm2(no);
 +      ctx.pf()->interpolation(ctx, coeff, aux1, 1);
 +      g = aux1[0];
 +      n = bgeot::compute_normal(ctx, ctx.face_num());
 +      n /= gmm::vect_norm2(n);
 +      break;
 +
 +    case 3 :// calculate [f_coeff] interpolating [friction_coeff] on [mf_coeff]
 +      if (pmf_coeff) {
 +        coeff.resize(pmf_coeff->nb_basic_dof_of_element(cv));
 +        gmm::copy(gmm::sub_vector
 +                  (friction_coeff, gmm::sub_index
 +                   (pmf_coeff->ind_basic_dof_of_element(cv))), coeff);
 +        ctx.pf()->interpolation(ctx, coeff, aux1, 1);
 +        f_coeff = aux1[0];
 +      }
 +      break;
 +
 +    default : GMM_ASSERT1(false, "Invalid option");
 +    }
 +  }
 +
 +
 +
 +
 +  template<typename MAT, typename VECT1>
 +  void asm_Nitsche_contact_rigid_obstacle_tangent_matrix
 +  (MAT &K, const mesh_im &mim,
 +   const getfem::mesh_fem &mf_u, const VECT1 &U,
 +   const getfem::mesh_fem &mf_obs, const VECT1 &obs,
 +   const getfem::mesh_fem *pmf_coeff, const VECT1 &f_coeff,
 +   scalar_type gamma, scalar_type lambda, scalar_type mu,
 +   const mesh_region &rg, int option = 1) {
 +
 +    contact_nitsche_nonlinear_term
 +      nterm1(6, gamma, lambda, mu, mf_u, U, mf_obs, obs, pmf_coeff, &f_coeff),
 +      nterm2(3, gamma, lambda, mu, mf_u, U, mf_obs, obs, pmf_coeff, &f_coeff),
 +      nterm3(4, gamma, lambda, mu, mf_u, U, mf_obs, obs, pmf_coeff, &f_coeff),
 +      nterm4(5, gamma, lambda, mu, mf_u, U, mf_obs, obs, pmf_coeff, &f_coeff);
 +
 +    const std::string aux_fems = pmf_coeff ? "#1,#2,#3" : "#1,#2";
 +
 +    getfem::generic_assembly assem;
 +    std::string as_str 
 +      = ((option == 0) ? "w1=comp(NonLin$1(#1,"+aux_fems+")(i,j,k,l).vGrad(#1)(:,i,j).vGrad(#1)(:,k,l));" : "")
 +      + "w2=comp(NonLin$2(#1,"+aux_fems+").vBase(#1).vBase(#1))(i,j,:,i,:,j);"
 +      + "w3=comp(NonLin$3(#1,"+aux_fems+").vBase(#1).vGrad(#1))(i,j,k,:,i,:,j,k);"
 +      + ((option == 0) ? "w4=comp(NonLin$4(#1,"+aux_fems+").vGrad(#1).vBase(#1))(i,j,k,:,i,j,:,k);" : "")
 +      + ((option == 0) ? "M(#1,#1)+=w1+w2+w3+w4;" : "M(#1,#1)+=w2+w3;");
 +
 +    assem.set(as_str);
-     assem.push_mi(mim);
-     assem.push_mf(mf_u);
-     assem.push_mf(mf_obs);
-     if (pmf_coeff) assem.push_mf(*pmf_coeff);
-     assem.push_nonlinear_term(&nterm1);
-     assem.push_nonlinear_term(&nterm2);
-     assem.push_nonlinear_term(&nterm3);
-     assem.push_nonlinear_term(&nterm4);
-     assem.push_mat(K);
-     assem.assembly(rg);
-   }
++=======
++        if (f_coeff_) f_coeff = (*f_coeff_)[0]; else f_coeff = scalar_type(0);
++      else {
++        friction_coeff.resize(pmf_coeff->nb_basic_dof());
++        pmf_coeff->extend_vector(*f_coeff_, friction_coeff);
++      }
++      if (WT_) {
++        WT.resize(mf_u.nb_basic_dof());
++        mf_u_.extend_vector(*WT_, WT);
++      }
++    }
 +
 +
++    void compute(fem_interpolation_context &ctx, bgeot::base_tensor &t) {
 +
-   template<typename VECT1>
-   void asm_Nitsche_contact_rigid_obstacle_rhs
-   (VECT1 &R, const mesh_im &mim,
-    const getfem::mesh_fem &mf_u, const VECT1 &U,
-    const getfem::mesh_fem &mf_obs, const VECT1 &obs,
-    const getfem::mesh_fem *pmf_coeff, const VECT1 &f_coeff,
-    scalar_type gamma, scalar_type lambda, scalar_type mu,
-    const mesh_region &rg, int option = 1) {
++      md->compute_Neumann_terms(1, *varname, mf_u, U, ctx, n, tG);
++      for (size_type i = 0; i < N; ++i)
++        zeta[i] = tG[i]
++          + ((g-un+alpha*un) * no[i] + alpha*wt[i] - alpha*u[i] ) / gamma;
++      if ((option == 1) || (theta != scalar_type(0))) {
++        coupled_projection(zeta, no, f_coeff, Pr);
++        gmm::add(Pr, gmm::scaled(tG.as_vector(), -scalar_type(1)), pgg);
++      }
 +
-     contact_nitsche_nonlinear_term
-       nterm1(1, gamma, lambda, mu, mf_u, U, mf_obs, obs, pmf_coeff, &f_coeff),
-       nterm2(2, gamma, lambda, mu, mf_u, U, mf_obs, obs, pmf_coeff, &f_coeff);
-     
++      switch (option) {
++      case 1:
++        {
++          ctx.pf()->real_base_value(ctx, tbv);
++          size_type qmult = N / ctx.pf()->target_dim();
++          short_type nbdofu = sizes_[0];
++          if (theta != scalar_type(0)) {
++            sizes_.resize(2);
++            sizes_[1] = N;
++            tp.adjust_sizes(sizes_);
++            sizes_.resize(1);
++            md->compute_Neumann_terms(2, *varname, mf_u, U, ctx, n, tp);
++          }
++          for (size_type i = 0; i < nbdofu; ++i) {
++            t[i] = scalar_type(0);
++            for (size_type j = 0; j < N; ++j) {
++              if (theta != scalar_type(0))
++                t[i] -= gamma*pgg[j]*theta*tp(i,j);
++              if (qmult == 1) t[i] += Pr[j]*tbv(i,j);
++            }
++            if (qmult > 1) t[i] += Pr[i%N] * tbv(i/N,0);
++          }
++        }
++        break;
++
++      case 2:
++        {
++          short_type nbdofu = sizes_[1];
++          sizes_[1] = N;
+           tp.adjust_sizes(sizes_);
+           sizes_[1] = nbdofu;
+           md->compute_Neumann_terms(2, *varname, mf_u, U, ctx, n, tp);
+           if (theta != scalar_type(0)) {
+             sizes_.resize(3); sizes_[2] = N;
+             tpp.adjust_sizes(sizes_);
+             sizes_.resize(2);
+             md->compute_Neumann_terms(3, *varname, mf_u, U, ctx, n, tpp);
+           }
+ 
+           ctx.pf()->real_base_value(ctx, tbv);
+           size_type qmult = N / ctx.pf()->target_dim();
+           coupled_projection_grad(zeta, no, f_coeff, GPr);
+ 
+           for (size_type i = 0; i < nbdofu; ++i)
+             for (size_type j = 0; j < nbdofu; ++j) {
+               scalar_type res(0);
+               for (size_type k = 0; k < N; ++k) {
+                 if (theta != scalar_type(0))
+                   res -= gamma * theta * tp(i,k) * tp(j,k);
+                 scalar_type tbvvi(0), tbvvjn(0);
+                 if (qmult == 1) {
+                   tbvvi = tbv(i,k);
+                   for (size_type l = 0; l < N; ++l) tbvvjn += no[l]*tbv(j,l);
+                 } else {
+                   tbvvi = ((i%N)==k) ? tbv(i/N,0) : scalar_type(0);
+                   tbvvjn = no[j%N]*tbv(j/N,0);
+                 }
+                 for (size_type l = 0; l < N; ++l) {
+                   scalar_type tbvvj(0);
+                   if (qmult == 1)
+                     tbvvj = tbv(j,l);
+                   else
+                     tbvvj=(((j%N)==l) ? tbv(j/N,0):scalar_type(0));
+                   res += GPr(k,l)
+                     * (gamma*tp(j,l) - alpha*tbvvj
+                        - (scalar_type(1)-alpha)*no[l]*tbvvjn)
+                     * (theta * tp(i,k) - tbvvi/gamma);
+                 }
+ 
+                 if (theta != scalar_type(0))
+                   res += theta*gamma*pgg[k] * tpp(i,j,k);
+               }
+               t(i,j) = res;
+             }
+         }
+         break;
+ 
+       case 3:
+         {
+           short_type nbdofu = sizes_[0];
+           short_type nbdofp = sizes_[1];
+           sizes_[0] = nbdofp; sizes_[1] = N;
+           tpaux.adjust_sizes(sizes_);
+           sizes_[0] = nbdofu; sizes_[1] = nbdofp;
+           md->compute_auxilliary_Neumann_terms(2, *varname, mf_u, U,
+                                                *auxvarname, ctx, n, tpaux);
+ 
+           if (theta != scalar_type(0)) {
+             sizes_[1] = N;
+             tp.adjust_sizes(sizes_);
+             sizes_[1] = nbdofp;
+             md->compute_Neumann_terms(2, *varname, mf_u, U, ctx, n, tp);
+             sizes_.resize(3); sizes_[2] = N;
+             tpp.adjust_sizes(sizes_);
+             sizes_.resize(2);
+             md->compute_auxilliary_Neumann_terms(3, *varname, mf_u, U,
+                                                  *auxvarname, ctx, n, tpp);
+           }
+ 
+           ctx.pf()->real_base_value(ctx, tbv);
+           size_type qmult = N / ctx.pf()->target_dim();
+           coupled_projection_grad(zeta, no, f_coeff, GPr);
+ 
+           for (size_type i = 0; i < nbdofu; ++i)
+             for (size_type j = 0; j < nbdofp; ++j) {
+               scalar_type res(0);
+               for (size_type k = 0; k < N; ++k) {
+                 if (theta != scalar_type(0))
+                   res -= gamma * theta * tp(i,k) * tpaux(j,k);
+                 scalar_type gttpik(0), tbvvi(0);
+                 if (theta != scalar_type(0)) gttpik = gamma*theta*tp(i,k);
+                 if (qmult == 1) tbvvi = tbv(i,k);
+                 else tbvvi=(((i%N)==k) ? tbv(i/N,0):scalar_type(0));
+                 for (size_type l = 0; l < N; ++l)
+                   res += GPr(k,l) * tpaux(j,l) * (gttpik - tbvvi);
+                 if (theta != scalar_type(0))
+                   res += theta*gamma*pgg[k] * tpp(i,j,k);
+               }
+               t(i,j) = res;
+             }
+         }
+         break;
+ 
+       default : GMM_ASSERT1(false, "Invalid option");
+       }
+     }
+ 
+ 
+     void prepare(fem_interpolation_context& ctx, size_type nb) {
+ 
+       size_type cv = ctx.convex_num();
+ 
+       switch (nb) { // last is computed first
+       case 1 : // calculate [u] and [un] interpolating [U] and [WT] on [mf_u]
+         slice_vector_on_basic_dof_of_element(mf_u, U, cv, coeff);
+         ctx.pf()->interpolation(ctx, coeff, u, N);
+         un = gmm::vect_sp(u, no);
+         if (gmm::vect_size(WT) == gmm::vect_size(U)) {
+           slice_vector_on_basic_dof_of_element(mf_u, WT, cv, coeff);
+           ctx.pf()->interpolation(ctx, coeff, wt, N);
+           wt -= gmm::vect_sp(wt, no) * no;
+         }
+         // computation of h for gamma = gamma0*h
+         scalar_type emax, emin; gmm::condition_number(ctx.K(),emax,emin);
+         gamma = gamma0 * emax * sqrt(scalar_type(N));
+         break;
+ 
+       case 2 : // calculate [g], [n] and [no] interpolating [obs] on [mf_obs]
+         slice_vector_on_basic_dof_of_element(mf_obs, obs, cv, coeff);
+         ctx.pf()->interpolation_grad(ctx, coeff, grad, 1);
+         gmm::copy(gmm::mat_row(grad, 0), no);
+         no /= -gmm::vect_norm2(no);
+         ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+         g = aux1[0];
+         n = bgeot::compute_normal(ctx, ctx.face_num());
+         n /= gmm::vect_norm2(n);
+         break;
+ 
+       case 3 : // calculate [f_coeff] interpolating [friction_coeff] on [mf_coeff]
+         if (pmf_coeff) {
+           slice_vector_on_basic_dof_of_element(*pmf_coeff, friction_coeff, cv, coeff);
+           ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+           f_coeff = aux1[0];
+         }
+         break;
+ 
+       default : GMM_ASSERT1(false, "Invalid option");
+       }
+     }
+   };
+ 
+ 
+ 
+   void asm_Nitsche_contact_rigid_obstacle_rhs
+     (model_real_plain_vector &R, const mesh_im &mim, const model &md,
+      const std::string &varname,
+      const getfem::mesh_fem &mf_u, const model_real_plain_vector &U,
+      const getfem::mesh_fem &mf_obs, const model_real_plain_vector &obs,
+      const getfem::mesh_fem *pmf_coeff, const model_real_plain_vector *f_coeff,
+      const model_real_plain_vector *WT,
+      scalar_type gamma0, scalar_type theta, scalar_type alpha,
+      const mesh_region &rg) {
+ 
+     contact_nitsche_nonlinear_term
+       nterm(1, gamma0, theta, alpha, md, varname, mf_u, U, mf_obs,
+             obs, "", 0, pmf_coeff, f_coeff, WT);
+ 
+     const std::string aux_fems = pmf_coeff ? "#1,#2,#3" : "#1,#2";
+ 
+     getfem::generic_assembly assem("V(#1)+=comp(NonLin$1(#1,"+aux_fems+"));");
+ 
+     assem.push_mi(mim);
+     assem.push_mf(mf_u);
+     assem.push_mf(mf_obs);
+     if (pmf_coeff) assem.push_mf(*pmf_coeff);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_vec(R);
+     assem.assembly(rg);
+   }
+ 
+ 
+   template<typename MAT>
+   void asm_Nitsche_contact_rigid_obstacle_tangent_matrix
+   (MAT &K, const mesh_im &mim, const model &md, const std::string &varname,
+    const getfem::mesh_fem &mf_u, const model_real_plain_vector &U,
+    const getfem::mesh_fem &mf_obs, const model_real_plain_vector &obs,
+    const getfem::mesh_fem *pmf_coeff, const model_real_plain_vector *f_coeff,
+    const model_real_plain_vector *WT,
+    scalar_type gamma0, scalar_type theta, scalar_type alpha,
+    const mesh_region &rg) {
+ 
+     contact_nitsche_nonlinear_term
+       nterm(2, gamma0, theta, alpha, md, varname, mf_u, U, mf_obs,
+             obs, "", 0, pmf_coeff, f_coeff, WT);
+ 
+     const std::string aux_fems = pmf_coeff ? "#1,#2,#3" : "#1,#2";
+ 
+     getfem::generic_assembly
+       assem("M(#1,#1)+=comp(NonLin$1(#1,"+aux_fems+"));");
+ 
++>>>>>>> upstream
+     assem.push_mi(mim);
+     assem.push_mf(mf_u);
+     assem.push_mf(mf_obs);
+     if (pmf_coeff) assem.push_mf(*pmf_coeff);
++<<<<<<< HEAD
++    assem.push_nonlinear_term(&nterm1);
++    assem.push_nonlinear_term(&nterm2);
++    assem.push_nonlinear_term(&nterm3);
++    assem.push_nonlinear_term(&nterm4);
++=======
+     assem.push_nonlinear_term(&nterm);
++>>>>>>> upstream
+     assem.push_mat(K);
+     assem.assembly(rg);
+   }
+ 
++<<<<<<< HEAD
++
++
++  template<typename VECT1>
++  void asm_Nitsche_contact_rigid_obstacle_rhs
++  (VECT1 &R, const mesh_im &mim,
++   const getfem::mesh_fem &mf_u, const VECT1 &U,
++   const getfem::mesh_fem &mf_obs, const VECT1 &obs,
++   const getfem::mesh_fem *pmf_coeff, const VECT1 &f_coeff,
++   scalar_type gamma, scalar_type lambda, scalar_type mu,
++   const mesh_region &rg, int option = 1) {
++
++    contact_nitsche_nonlinear_term
++      nterm1(1, gamma, lambda, mu, mf_u, U, mf_obs, obs, pmf_coeff, &f_coeff),
++      nterm2(2, gamma, lambda, mu, mf_u, U, mf_obs, obs, pmf_coeff, &f_coeff);
++    
 +    const std::string aux_fems = pmf_coeff ? "#1,#2,#3" : "#1,#2";
 +    
 +    getfem::generic_assembly assem;
 +    std::string as_str = 
 +      "V(#1)+=comp(NonLin$1(#1,"+aux_fems+").vBase(#1))(i,:,i); "
 +      + ((option == 0) ? "V(#1)+=comp(NonLin$2(#1,"+aux_fems+").vGrad(#1))(i,j,:,i,j)" : "");
 +
 +    assem.set(as_str);
++=======
+   template<typename MAT>
+   void asm_Nitsche_contact_rigid_obstacle_tangent_matrix_auxilliary
+   (MAT &K, const mesh_im &mim, const model &md, const std::string &varname,
+    const getfem::mesh_fem &mf_u, const model_real_plain_vector &U,
+    const getfem::mesh_fem &mf_obs, const model_real_plain_vector &obs,
+    const getfem::mesh_fem *pmf_coeff, const model_real_plain_vector *f_coeff,
+    const model_real_plain_vector *WT,
+    scalar_type gamma0, scalar_type theta, scalar_type alpha,
+    const std::string &auxvarname, const getfem::mesh_fem &mf_p,
+    const mesh_region &rg) {
+ 
+     contact_nitsche_nonlinear_term
+       nterm(3, gamma0, theta, alpha, md, varname, mf_u, U, mf_obs,
+             obs, auxvarname, &mf_p, pmf_coeff, f_coeff, WT);
+ 
+     const std::string aux_fems = pmf_coeff ? "#1,#2,#3" : "#1,#2";
+     const std::string p_fem = pmf_coeff ? "#4" : "#3";
+ 
+     getfem::generic_assembly
+       assem("M(#1,"+p_fem+")+=comp(NonLin$1(#1,"+aux_fems+"));");
+ 
++>>>>>>> upstream
      assem.push_mi(mim);
      assem.push_mf(mf_u);
      assem.push_mf(mf_obs);
      if (pmf_coeff) assem.push_mf(*pmf_coeff);
++<<<<<<< HEAD
 +    assem.push_nonlinear_term(&nterm1);
 +    assem.push_nonlinear_term(&nterm2);
 +    assem.push_vec(R);
++=======
+     assem.push_mf(mf_p);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_mat(K);
++>>>>>>> upstream
      assem.assembly(rg);
    }
  
  
    struct Nitsche_contact_rigid_obstacle_brick : public virtual_brick {
  
++<<<<<<< HEAD
++=======
+     scalar_type theta;
+     bool contact_only;
+ 
++>>>>>>> upstream
      virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
                                          const model::varnamelist &vl,
                                          const model::varnamelist &dl,
@@@ -2765,19 -2932,17 +3992,33 @@@
                                          build_version version) const {
        // Integration method
        GMM_ASSERT1(mims.size() == 1, "Nitsche contact with rigid obstacle "
++<<<<<<< HEAD
 +		  "bricks need a single mesh_im");
 +      const mesh_im &mim = *mims[0];
 +
 +      // Variables : u
 +      GMM_ASSERT1(vl.size() == 1,
 +                  "Nitsche contact with rigid obstacle bricks need a "
 +		  "single variable");
 +      const model_real_plain_vector &u = md.real_variable(vl[0]);
 +      const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
 +
 +      // Data : obs, r, [lambda,] [friction_coeff,] [alpha,] [WT]
 +      GMM_ASSERT1(dl.size() == 5, "Wrong number of data for Nitsche "
 +		  "contact with rigid obstacle brick");
++=======
+                   "bricks need a single mesh_im");
+       const mesh_im &mim = *mims[0];
+ 
+ 
+       const model_real_plain_vector &u = md.real_variable(vl[0]);
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+ 
+       // Data : obs, r, theta, [alpha,] [WT]
+       GMM_ASSERT1(dl.size() >= (contact_only ? 2:3),
+                   "Wrong number of data for Nitsche "
+                   "contact with rigid obstacle brick");
++>>>>>>> upstream
  
        const model_real_plain_vector &obs = md.real_variable(dl[0]);
        const mesh_fem &mf_obs = md.mesh_fem_of_variable(dl[0]);
@@@ -2785,55 -2950,77 +4026,124 @@@
        GMM_ASSERT1(sl == 1, "the data corresponding to the obstacle has not "
                    "the right format");
  
++<<<<<<< HEAD
 +      const model_real_plain_vector &vr = md.real_variable(dl[1]);
 +      GMM_ASSERT1(gmm::vect_size(vr) == 1, "Parameter r should be a scalar");
 +
 +      const model_real_plain_vector *f_coeff = 0;
 +      const mesh_fem *pmf_coeff = 0;
 +      
 +      f_coeff = &(md.real_variable(dl[2]));
 +      pmf_coeff = md.pmesh_fem_of_variable(dl[2]);
 +      sl = gmm::vect_size(*f_coeff);
 +      if (pmf_coeff) { sl*= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
 +      GMM_ASSERT1(sl == 1, "the data corresponding to the friction "
 +		  "coefficient has not the right format");
 +      
 +      const model_real_plain_vector &vlambda = md.real_variable(dl[3]);
 +      GMM_ASSERT1(gmm::vect_size(vlambda) == 1,
 +		  "Parameter lambda should be a scalar");
 +      const model_real_plain_vector &vmu = md.real_variable(dl[4]);
 +      GMM_ASSERT1(gmm::vect_size(vmu) == 1, "Parameter mu should be a scalar");
 +
 +
 +      GMM_ASSERT1(matl.size() == 1, "Wrong number of terms for "
 +                  "Nitsche contact with rigid obstacle brick");
 +
++=======
+       const model_real_plain_vector &vgamma0 = md.real_variable(dl[1]);
+       GMM_ASSERT1(gmm::vect_size(vgamma0) == 1,
+                   "Parameter gamma0 should be a scalar");
+       scalar_type gamma0 = vgamma0[0];
+ 
+       const model_real_plain_vector *f_coeff = 0;
+       const mesh_fem *pmf_coeff = 0;
+ 
+       if (!contact_only) {
+         f_coeff = &(md.real_variable(dl[2]));
+         pmf_coeff = md.pmesh_fem_of_variable(dl[2]);
+         sl = gmm::vect_size(*f_coeff);
+         if (pmf_coeff)
+           { sl*= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
+         GMM_ASSERT1(sl == 1, "the data corresponding to the friction "
+                     "coefficient has not the right format");
+       }
+ 
+       scalar_type alpha = 1;
+       if (!contact_only && dl.size() >= 4) {
+         GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[3])) == 1,
+                     "Parameter alpha should be a scalar");
+         alpha = md.real_variable(dl[3])[0];
+       }
+ 
+       const model_real_plain_vector *WT
+         = (!contact_only && dl.size()>=5) ? &(md.real_variable(dl[4])) : 0;
+ 
+ 
+       GMM_ASSERT1(matl.size() == vl.size(), "Wrong number of terms for "
+                   "Nitsche contact with rigid obstacle brick");
+ 
+ 
++>>>>>>> upstream
        mesh_region rg(region);
        mf_u.linked_mesh().intersect_with_mpi_region(rg);
  
        if (version & model::BUILD_MATRIX) {
          GMM_TRACE2("Nitsche contact with rigid obstacle tangent term");
          gmm::clear(matl[0]);
++<<<<<<< HEAD
 +	asm_Nitsche_contact_rigid_obstacle_tangent_matrix
 +	  (matl[0], mim, mf_u, u, mf_obs, obs,  pmf_coeff, *f_coeff,
 +	   vr[0], vlambda[0], vmu[0], rg);
++=======
+         asm_Nitsche_contact_rigid_obstacle_tangent_matrix
+           (matl[0], mim, md, vl[0], mf_u, u, mf_obs, obs,  pmf_coeff,
+            f_coeff, WT, gamma0, theta, alpha, rg);
+ 
+         for (size_type i = 1; i < vl.size(); ++i) { // Auxilliary variables
+           gmm::clear(matl[i]);
+           asm_Nitsche_contact_rigid_obstacle_tangent_matrix_auxilliary
+             (matl[i], mim, md, vl[0], mf_u, u, mf_obs, obs, pmf_coeff,
+              f_coeff, WT, gamma0, theta, alpha, vl[i],
+              md.mesh_fem_of_variable(vl[i]), rg);
+         }
++>>>>>>> upstream
        }
  
        if (version & model::BUILD_RHS) {
          gmm::clear(vecl[0]);
++<<<<<<< HEAD
 +	asm_Nitsche_contact_rigid_obstacle_rhs
 +	  (vecl[0], mim, mf_u, u, mf_obs, obs, pmf_coeff, *f_coeff,
 +	   vr[0], vlambda[0], vmu[0], rg);
++=======
+         asm_Nitsche_contact_rigid_obstacle_rhs
+           (vecl[0], mim, md, vl[0], mf_u, u, mf_obs, obs,  pmf_coeff,
+            f_coeff, WT, gamma0, theta, alpha, rg);
++>>>>>>> upstream
        }
  
      }
  
++<<<<<<< HEAD
 +    Nitsche_contact_rigid_obstacle_brick(void) {
 +      set_flags("Integral Nitsche contact and friction with rigid "
 +                "obstacle brick",
 +                false /* is linear*/, false /* is symmetric */,
 +                true /* is coercive */, true /* is real */,
 +                false /* is complex */);
++=======
+     Nitsche_contact_rigid_obstacle_brick(scalar_type theta_, bool nofriction) {
+       theta = theta_;
+       contact_only = nofriction;
+       bool co = (theta_ == scalar_type(1)) && nofriction;
+       set_flags("Integral Nitsche contact and friction with rigid "
+                 "obstacle brick",
+                 false /* is linear*/, co /* is symmetric */,
+                 co /* is coercive */, true /* is real */,
+                 false /* is complex */, false /* compute each time */,
+                 false /* has a Neumann term */);
++>>>>>>> upstream
      }
  
    };
@@@ -2841,1142 -3028,1199 +4151,2335 @@@
  
    size_type add_Nitsche_contact_with_rigid_obstacle_brick
    (model &md, const mesh_im &mim, const std::string &varname_u,
++<<<<<<< HEAD
 +   const std::string &dataname_obs, const std::string &dataname_r,
 +   const std::string &dataname_friction_coeff,
 +   const std::string &dataname_lambda, const std::string &dataname_mu,
 +   size_type region) {
 +
 +    pbrick pbr = new Nitsche_contact_rigid_obstacle_brick;
 +
 +    model::termlist tl;
 +    tl.push_back(model::term_description(varname_u, varname_u, false));
 +
 +    model::varnamelist dl(1, dataname_obs);
 +    dl.push_back(dataname_r);
 +    dl.push_back(dataname_friction_coeff);
 +    dl.push_back(dataname_lambda);
 +    dl.push_back(dataname_mu);
 +
 +    model::varnamelist vl(1, varname_u);
 +
 +    return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
 +  }
 +
 +#endif
 +
 +
 +
 +  //=========================================================================
 +  //
 +  //  Large sliding brick.
 +  //
 +  //=========================================================================
 +
 +  //=========================================================================
 +  // 0)- Some basic assembly functions
 +  //=========================================================================
 +
 +  template <typename MAT1, typename MAT2>
 +  void mat_elem_assembly(const MAT1 &M_, const MAT2 &Melem,
 +			 const mesh_fem &mf1, size_type cv1,
 +			 const mesh_fem &mf2, size_type cv2) {
 +    MAT1 &M = const_cast<MAT1 &>(M_);
 +    typedef typename gmm::linalg_traits<MAT1>::value_type T;
 +    T val;
 +    std::vector<size_type> cvdof1(mf1.ind_basic_dof_of_element(cv1).begin(),
 +				  mf1.ind_basic_dof_of_element(cv1).end());
 +    std::vector<size_type> cvdof2(mf2.ind_basic_dof_of_element(cv2).begin(),
 +				  mf2.ind_basic_dof_of_element(cv2).end());
 +
 +    GMM_ASSERT1(cvdof1.size() == gmm::mat_nrows(Melem)
 +		&& cvdof2.size() == gmm::mat_ncols(Melem),
 +		"Dimensions mismatch");
 +    
 +    if (mf1.is_reduced()) {
 +      if (mf2.is_reduced()) {
 +	for (size_type i = 0; i < cvdof1.size(); ++i)
 +	  for (size_type j = 0; j < cvdof2.size(); ++j)
 +	    if ((val = Melem(i,j)) != T(0))
 +	      asmrankoneupdate
 +		(M, gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
 +		 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
 +      } else {
 +	for (size_type i = 0; i < cvdof1.size(); ++i)
 +	  for (size_type j = 0; j < cvdof2.size(); ++j)
 +	    if ((val = Melem(i,j)) != T(0))
 +	      asmrankoneupdate
 +		(M, gmm::mat_row(mf1.extension_matrix(), cvdof1[i]),
 +		 cvdof2[j], val);
 +      }
 +    } else {
 +      if (mf2.is_reduced()) {
 +	for (size_type i = 0; i < cvdof1.size(); ++i)
 +	  for (size_type j = 0; j < cvdof2.size(); ++j)
 +	    if ((val = Melem(i,j)) != T(0))
 +	      asmrankoneupdate
 +		(M, cvdof1[i],
 +		 gmm::mat_row(mf2.extension_matrix(), cvdof2[j]), val);
 +      } else {
 +	for (size_type i = 0; i < cvdof1.size(); ++i)
 +	  for (size_type j = 0; j < cvdof2.size(); ++j)
 +	    if ((val = Melem(i,j)) != T(0))
 +	      M(cvdof1[i], cvdof2[j]) += val;
 +      }
 +    }
 +  }
 +
 +
 +  template <typename VEC1, typename VEC2>
 +  void vec_elem_assembly(const VEC1 &V_, const VEC2 &Velem,
 +			 const mesh_fem &mf, size_type cv) {
 +    VEC1 &V = const_cast<VEC1 &>(V_);
 +    typedef typename gmm::linalg_traits<VEC1>::value_type T;
 +    std::vector<size_type> cvdof(mf.ind_basic_dof_of_element(cv).begin(),
 +				 mf.ind_basic_dof_of_element(cv).end());
 +
 +    GMM_ASSERT1(cvdof.size() == gmm::vect_size(Velem), "Dimensions mismatch");
 +    
 +    if (mf.is_reduced()) {
 +      T val;
 +      for (size_type i = 0; i < cvdof.size(); ++i)
 +	if ((val = Velem[i]) != T(0))
 +	  gmm::add(gmm::scaled(gmm::mat_row(mf.extension_matrix(), cvdof[i]),
 +			       val), V);
 +    } else {
 +      for (size_type i = 0; i < cvdof.size(); ++i) V[cvdof[i]] += Velem[i];
 +    }
 +  }
 +  
 +
 +  //=========================================================================
 +  // 1)- Structure which stores the contact boundaries and rigid obstacles
 +  //=========================================================================
 +
 +  struct contact_frame {
 +    bool frictionless;
 +    size_type N;
 +    scalar_type friction_coef;
 +    std::vector<const model_real_plain_vector *> Us;
 +    std::vector<model_real_plain_vector> ext_Us;
 +    std::vector<const model_real_plain_vector *> lambdas;
 +    std::vector<model_real_plain_vector> ext_lambdas;
 +    struct contact_boundary {
 +      size_type region;                 // Boundary number
 +      const getfem::mesh_fem *mfu;      // F.e.m. for the displacement.
 +      size_type ind_U;                  // Index of displacement.
 +      const getfem::mesh_fem *mflambda; // F.e.m. for the multiplier.
 +      size_type ind_lambda;             // Index of multiplier.
 +    };
 +    std::vector<contact_boundary> contact_boundaries;
 +
 +    gmm::dense_matrix< model_real_sparse_matrix * > UU;
 +    gmm::dense_matrix< model_real_sparse_matrix * > UL;
 +    gmm::dense_matrix< model_real_sparse_matrix * > LU;
 +    gmm::dense_matrix< model_real_sparse_matrix * > LL;
 +
 +    std::vector< model_real_plain_vector *> Urhs;
 +    std::vector< model_real_plain_vector *> Lrhs;
 +    
 +    
 +
 +    std::vector<std::string> coordinates;
 +    base_node pt_eval;
 +#if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
 +    std::vector<mu::Parser> obstacles_parsers;
 +#endif
 +    std::vector<std::string> obstacles;
 +    std::vector<std::string> obstacles_velocities;
 +
 +    size_type add_U(const getfem::mesh_fem &mfu,
 +		    const model_real_plain_vector &U) {
 +      size_type i = 0;
 +      for (; i < Us.size(); ++i) if (Us[i] == &U) return i;
 +      Us.push_back(&U);
 +      model_real_plain_vector ext_U(mfu.nb_basic_dof()); // means that the structure has to be build each time ... to be changed. ATTENTION : la m�me variable ne doit pas �tre �tendue dans deux vecteurs diff�rents.
 +      mfu.extend_vector(U, ext_U);
 +      ext_Us.push_back(ext_U);
 +      return i;
 +    }
 +
 +    size_type add_lambda(const getfem::mesh_fem &mfl,
 +			 const model_real_plain_vector &l) {
 +      size_type i = 0;
 +      for (; i < lambdas.size(); ++i) if (lambdas[i] == &l) return i;
 +      lambdas.push_back(&l);
 +      model_real_plain_vector ext_l(mfl.nb_basic_dof()); // means that the structure has to be build each time ... to be changed. ATTENTION : la m�me variable ne doit pas �tre �tendue dans deux vecteurs diff�rents.
 +      mfl.extend_vector(l, ext_l);
 +      ext_lambdas.push_back(ext_l);
 +      return i;
 +    }
 +
 +
 +    const getfem::mesh_fem &mfu_of_boundary(size_type n) const
 +    { return *(contact_boundaries[n].mfu); }
 +    const getfem::mesh_fem &mflambda_of_boundary(size_type n) const
 +    { return *(contact_boundaries[n].mflambda); }
 +    const model_real_plain_vector &disp_of_boundary(size_type n) const
 +    { return ext_Us[contact_boundaries[n].ind_U]; }
 +    const model_real_plain_vector &lambda_of_boundary(size_type n) const
 +    { return ext_lambdas[contact_boundaries[n].ind_lambda]; }
 +    size_type region_of_boundary(size_type n) const
 +    { return contact_boundaries[n].region; }
 +    model_real_sparse_matrix &UU_matrix(size_type n, size_type m) const
 +    { return *(UU(contact_boundaries[n].ind_U, contact_boundaries[m].ind_U)); }
 +    model_real_sparse_matrix &LU_matrix(size_type n, size_type m) const {
 +      return *(LU(contact_boundaries[n].ind_lambda,
 +		  contact_boundaries[m].ind_U));
 +    }
 +    model_real_sparse_matrix &UL_matrix(size_type n, size_type m) const {
 +      return *(UL(contact_boundaries[n].ind_U,
 +		  contact_boundaries[m].ind_lambda));
 +    }
 +    model_real_sparse_matrix &LL_matrix(size_type n, size_type m) const {
 +      return *(LL(contact_boundaries[n].ind_lambda,
 +		  contact_boundaries[m].ind_lambda));
 +    }
 +    model_real_plain_vector &U_vector(size_type n) const
 +    { return *(Urhs[contact_boundaries[n].ind_U]); }
 +    model_real_plain_vector &L_vector(size_type n) const
 +    { return *(Lrhs[contact_boundaries[n].ind_lambda]); }
 +
 +    contact_frame(size_type NN) : N(NN), coordinates(N), pt_eval(N) {
 +      if (N > 0) coordinates[0] = "x";
 +      if (N > 1) coordinates[1] = "y";
 +      if (N > 2) coordinates[2] = "z";
 +      if (N > 3) coordinates[3] = "w";
 +      GMM_ASSERT1(N <= 4, "Complete the definition for contact in "
 +		  "dimension greater than 4");
 +    }
 +
 +    size_type add_obstacle(const std::string &obs) {
 +      size_type ind = obstacles.size();
 +      obstacles.push_back(obs);
 +      obstacles_velocities.push_back("");
 +#if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H 
 +      mu::Parser mu;
 +      obstacles_parsers.push_back(mu);
 +      obstacles_parsers[ind].SetExpr(obstacles[ind]);
 +      for (size_type k = 0; k < N; ++k)
 +	obstacles_parsers[ind].DefineVar(coordinates[k], &pt_eval[k]);
 +#else
 +      GMM_ASSERT1(false, "You have to link muparser with getfem to deal "
 +		  "with rigid body obstacles");
 +#endif
 +      return ind;
 +    }
 +
 +    size_type add_boundary(const getfem::mesh_fem &mfu,
 +			   const model_real_plain_vector &U,
 +			   const getfem::mesh_fem &mfl,
 +			   const model_real_plain_vector &l,
 +			   size_type reg) {
 +      contact_boundary cb;
 +      cb.region = reg;
 +      cb.mfu = &mfu;
 +      cb.mflambda = &mfl;
 +      cb.ind_U = add_U(mfu, U);
 +      cb.ind_lambda = add_lambda(mfl, l);
 +      size_type ind = contact_boundaries.size();
 +      contact_boundaries.push_back(cb);
 +      gmm::resize(UU, ind+1, ind+1);
 +      gmm::resize(UL, ind+1, ind+1);
 +      gmm::resize(LU, ind+1, ind+1);
 +      gmm::resize(LL, ind+1, ind+1);
 +      gmm::resize(Urhs, ind+1);
 +      gmm::resize(Lrhs, ind+1);
 +      return ind;
 +    }
 +
 +  };
 +
 +
 +  //=========================================================================
 +  // 2)- Structure which computes the contact pairs, rhs and tangent terms
 +  //=========================================================================
 +
 +  struct contact_elements {
 +
 +    contact_frame &cf;   // contact frame description.
 +    
 +    // list des enrichissements pour ses points : y0, d0, element ...
 +    bgeot::rtree element_boxes;  // influence regions of boundary elements
 +    // list des enrichissements of boundary elements
 +    std::vector<size_type> boundary_of_elements;
 +    std::vector<size_type> ind_of_elements;
 +    std::vector<size_type> face_of_elements;
 +    std::vector<base_node> unit_normal_of_elements;
 +
 +    contact_elements(contact_frame &ccf) : cf(ccf) {}
 +    void init(void);
 +    bool add_point_contribution(size_type boundary_num,
 +				getfem::fem_interpolation_context &ctxu,
 +				getfem::fem_interpolation_context &ctxl,
 +				scalar_type weight, scalar_type f_coeff,
 +				scalar_type r, model::build_version version);
 +  };
 +
 +
 +  void contact_elements::init(void) {
 +    fem_precomp_pool fppool;
 +    // compute the influence regions of boundary elements. To be run
 +    // before the assembly of contact terms.
 +    element_boxes.clear();
 +    unit_normal_of_elements.resize(0);
 +    boundary_of_elements.resize(0);
 +    ind_of_elements.resize(0);
 +    face_of_elements.resize(0);
 +    
 +    size_type N = 0;
 +    base_matrix G;
 +    model_real_plain_vector coeff;
 +    for (size_type i = 0; i < cf.contact_boundaries.size(); ++i) {
 +      size_type bnum = cf.region_of_boundary(i);
 +      const mesh_fem &mfu = cf.mfu_of_boundary(i);
 +      const model_real_plain_vector &U = cf.disp_of_boundary(i);
 +      const mesh &m = mfu.linked_mesh();
 +      if (i == 0) N = m.dim();
 +      GMM_ASSERT1(m.dim() == N,
 +		  "Meshes are of mixed dimensions, cannot deal with that");
 +      base_node val(N), bmin(N), bmax(N), n0(N), n(N), n_mean(N);
 +      base_matrix grad(N,N);
 +      mesh_region region = m.region(bnum);
 +      GMM_ASSERT1(mfu.get_qdim() == N,
 +		  "Wrong mesh_fem qdim to compute contact pairs");
 +      
 +      dal::bit_vector points_already_interpolated;
 +      std::vector<base_node> transformed_points(m.nb_max_points());
 +      for (getfem::mr_visitor v(region,m); !v.finished(); ++v) {
 +	size_type cv = v.cv();
 +	bgeot::pgeometric_trans pgt = m.trans_of_convex(cv);
 +	pfem pf_s = mfu.fem_of_element(cv);
 +	size_type nbd_t = pgt->nb_points();
 +	size_type cvnbdof = mfu.nb_basic_dof_of_element(cv);
 +	coeff.resize(cvnbdof);
 +	mesh_fem::ind_dof_ct::const_iterator
 +	  itdof = mfu.ind_basic_dof_of_element(cv).begin();
 +	for (size_type k = 0; k < cvnbdof; ++k, ++itdof) coeff[k]=U[*itdof];
 +	bgeot::vectors_to_base_matrix
 +	  (G, mfu.linked_mesh().points_of_convex(cv));
 +	
 +	pfem_precomp pfp = fppool(pf_s, &(pgt->geometric_nodes()));
 +	fem_interpolation_context ctx(pgt,pfp,size_type(-1), G, cv,
 +				      size_type(-1));
 +	
 +	size_type nb_pt_on_face = 0;
 +	gmm::clear(n_mean);
 +	for (short_type ip = 0; ip < nbd_t; ++ip) {
 +	  size_type ind = m.ind_points_of_convex(cv)[ip];
 +	  
 +	  // computation of transformed vertex
 +	  if (!(points_already_interpolated.is_in(ind))) {
 +	    ctx.set_ii(ip);
 +	    pf_s->interpolation(ctx, coeff, val, dim_type(N));
 +	    val += ctx.xreal();
 +	    transformed_points[ind] = val;
 +	    points_already_interpolated.add(ind);	  
 +	  } else {
 +	    val = transformed_points[ind];
 +	  }
 +	  // computation of unit normal vector if the vertex is on the face
 +	  bool is_on_face = false;
 +	  bgeot::pconvex_structure cvs = pgt->structure();
 +	  for (size_type k = 0; k < cvs->nb_points_of_face(v.f()); ++k)
 +	    if (cvs->ind_points_of_face(v.f())[k] == ip) is_on_face = true;
 +	  if (is_on_face) {
 +	    ctx.set_ii(ip); 
 +	    n0 = bgeot::compute_normal(ctx, v.f());
 +	    pf_s->interpolation_grad(ctx, coeff, grad, dim_type(N));
 +	    gmm::add(gmm::identity_matrix(), grad);
 +	    scalar_type J = gmm::lu_inverse(grad);
 +	    if (J <= scalar_type(0)) GMM_WARNING1("Inverted element ! " << J);
 +	    gmm::mult(gmm::transposed(grad), n0, n);
 +	    n /= gmm::vect_norm2(n);
 +	    n_mean += n;
 +	    ++nb_pt_on_face;
 +	  }
 +	  
 +	  if (ip == 0) // computation of bounding box
 +	    bmin = bmax = val;
 +	  else {
 +	    for (size_type k = 0; k < N; ++k) {
 +	      bmin[k] = std::min(bmin[k], val[k]);
 +	      bmax[k] = std::max(bmax[k], val[k]);
 +	    }
 +	  }
 +	}
 +	
 +	GMM_ASSERT1(nb_pt_on_face,
 +		    "This element has not vertex on considered face !");
 +	
 +	// Computation of influence box :
 +	// offset of the bounding box relatively to its "diameter"
 +	scalar_type h = bmax[0] - bmin[0];
 +	for (size_type k = 1; k < N; ++k)
 +	  h = std::max(h, bmax[k] - bmin[k]);
 +	for (size_type k = 0; k < N; ++k)
 +	  { bmin[k] -= h; bmax[k] += h; }
 +	
 +	// Store the influence box and additional information.
 +	element_boxes.add_box(bmin, bmax, unit_normal_of_elements.size());
 +	n_mean /= gmm::vect_norm2(n_mean);
 +	unit_normal_of_elements.push_back(n_mean);
 +	boundary_of_elements.push_back(i);
 +	ind_of_elements.push_back(cv);
 +	face_of_elements.push_back(v.f());
 +      }
 +    }
 +  }
 +  
 +
 +
 +  bool contact_elements::add_point_contribution
 +  (size_type boundary_num, getfem::fem_interpolation_context &ctxu,
 +   getfem::fem_interpolation_context &ctxl, scalar_type weight,
 +   scalar_type f_coeff, scalar_type r, model::build_version version) {
 +    const mesh_fem &mfu = cf.mfu_of_boundary(boundary_num);
 +    const mesh_fem &mfl = cf.mflambda_of_boundary(boundary_num);
 +    const model_real_plain_vector &U = cf.disp_of_boundary(boundary_num);
 +    const model_real_plain_vector &L = cf.lambda_of_boundary(boundary_num);
 +    size_type N = mfu.get_qdim();
 +    base_node x0 = ctxu.xreal();
 +    bool noisy = false;
 +
 +    // ----------------------------------------------------------
 +    // Computation of the point coordinates and the unit normal
 +    // vector in real configuration
 +    // ----------------------------------------------------------
 +    
 +    base_node n0 = bgeot::compute_normal(ctxu, ctxu.face_num());
 +    scalar_type face_factor = gmm::vect_norm2(n0);
 +    size_type cv = ctxu.convex_num();
 +    base_small_vector n(N), val(N), h(N);
 +    base_matrix gradinv(N,N), grad(N,N), gradtot(N,N), G;
 +    size_type cvnbdofu = mfu.nb_basic_dof_of_element(cv);
 +    size_type cvnbdofl = mfl.nb_basic_dof_of_element(cv);
 +    base_vector coeff(cvnbdofu);
 +    gmm::copy(gmm::sub_vector
 +	      (U, gmm::sub_index
 +	       (mfu.ind_basic_dof_of_element(cv))), coeff);
 +    ctxu.pf()->interpolation(ctxu, coeff, val, dim_type(N));
 +    base_node x = x0 + val;
 +    
 +    ctxu.pf()->interpolation_grad(ctxu, coeff, gradinv, dim_type(N));
 +    gmm::add(gmm::identity_matrix(), gradinv);
 +    scalar_type J = gmm::lu_inverse(gradinv); // remplacer par une r�solution...
 +    if (J <= scalar_type(0)) {
 +      GMM_WARNING1("Inverted element !");
 +      
 +      GMM_ASSERT1(!(version & model::BUILD_MATRIX), "Impossible to build "
 +		  "tangent matrix for large sliding contact");
 +      if (version & model::BUILD_RHS) {
 +	base_vector Velem(cvnbdofl);
 +	for (size_type i = 0; i < cvnbdofl; ++i) Velem[i] = 1E200;
 +	vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
 +	return false;
 +      }
 +    }
 +
 +    gmm::mult(gmm::transposed(gradinv), n0, n);
 +    n /= gmm::vect_norm2(n);
 +    
 +    // ----------------------------------------------------------
 +    // Selection of influence boxes
 +    // ----------------------------------------------------------
 +    
 +    bgeot::rtree::pbox_set bset;
 +    element_boxes.find_boxes_at_point(x, bset);
 +    
 +    if (noisy) cout << "Number of boxes found : " << bset.size() << endl; 
 +    
 +    // ----------------------------------------------------------
 +    // Eliminates some influence boxes with the mean normal
 +    // criterion : should at least eliminate the original element.
 +    // ----------------------------------------------------------
 +    
 +    bgeot::rtree::pbox_set::iterator it = bset.begin(), itnext;
 +    for (; it != bset.end(); it = itnext) {
 +      itnext = it; ++itnext;
 +      if (gmm::vect_sp(unit_normal_of_elements[(*it)->id], n)
 +	  >= -scalar_type(1)/scalar_type(20)) bset.erase(it);
 +    }
 +    
 +    if (noisy)
 +      cout << "Number of boxes satisfying the unit normal criterion : "
 +	   << bset.size() << endl; 
 +    
 +    
 +    // ----------------------------------------------------------
 +    // For each remaining influence box, compute y0, the corres-
 +    // ponding unit normal vector and eliminate wrong auto-contact
 +    // situations with a test on |x0-y0|
 +    // ----------------------------------------------------------
 +    
 +    it = bset.begin();
 +    std::vector<base_node> y0s, y0_refs;
 +    std::vector<base_small_vector> n0_y0s;
 +    std::vector<scalar_type> d0s;
 +    std::vector<scalar_type> d1s;
 +    std::vector<size_type> elt_nums;
 +    std::vector<fem_interpolation_context> ctx_y0s;
 +    for (; it != bset.end(); ++it) {
 +      size_type boundary_num_y0 = boundary_of_elements[(*it)->id];
 +      size_type cv_y0 = ind_of_elements[(*it)->id];
 +      short_type face_y0 = short_type(face_of_elements[(*it)->id]);
 +      const mesh_fem &mfu_y0 = cf.mfu_of_boundary(boundary_num_y0);
 +      pfem pf_s = mfu_y0.fem_of_element(cv_y0);
 +      const model_real_plain_vector &U_y0
 +	= cf.disp_of_boundary(boundary_num_y0);
 +      const mesh &m = mfu_y0.linked_mesh();
 +      bgeot::pgeometric_trans pgt_y0 = m.trans_of_convex(cv_y0);
 +      bgeot::pconvex_structure cvs_y0 = pgt_y0->structure();
 +      
 +      // Find an interior point (in order to promote the more interior
 +      // y0 in case of locally non invertible transformation.
 +      size_type ind_dep_point = 0;
 +      for (; ind_dep_point < cvs_y0->nb_points(); ++ind_dep_point) {
 +	bool is_on_face = false;
 +	for (size_type k = 0;
 +	     k < cvs_y0->nb_points_of_face(face_y0); ++k)
 +	  if (cvs_y0->ind_points_of_face(face_y0)[k]
 +	      == ind_dep_point) is_on_face = true;
 +	if (!is_on_face) break;
 +      }
 +      GMM_ASSERT1(ind_dep_point < cvs_y0->nb_points(), 
 +		  "No interior point found !");
 +      
 +      base_node y0_ref = pgt_y0->convex_ref()->points()[ind_dep_point];
 +      
 +      size_type cvnbdof_y0 = mfu_y0.nb_basic_dof_of_element(cv_y0);
 +      coeff.resize(cvnbdof_y0);
 +      mesh_fem::ind_dof_ct::const_iterator
 +	itdof = mfu_y0.ind_basic_dof_of_element(cv_y0).begin();
 +      for (size_type k = 0; k < cvnbdof_y0; ++k, ++itdof)
 +	coeff[k] = U_y0[*itdof];
 +      // if (pf_s->need_G()) 
 +      bgeot::vectors_to_base_matrix
 +	(G, mfu_y0.linked_mesh().points_of_convex(cv_y0));
 +      
 +      fem_interpolation_context ctx_y0(pgt_y0, pf_s, y0_ref, G, cv_y0,
 +				       size_type(-1));
 +      
 +      size_type newton_iter = 0;
 +      for(;;) { // Newton algorithm to invert geometric transformation
 +	
 +	pf_s->interpolation(ctx_y0, coeff, val, dim_type(N));
 +	val += ctx_y0.xreal() - x;
 +	scalar_type init_res = gmm::vect_norm2(val);
 +	
 +	if (init_res < 1E-12) break;
 +	if (newton_iter > 100) {
 +	  GMM_WARNING1("Newton has failed to invert transformation"); // il faudrait faire qlq chose d'autre ... !
 +	  GMM_ASSERT1(!(version & model::BUILD_MATRIX), "Impossible to build "
 +		    "tangent matrix for large sliding contact");
 +	  if (version & model::BUILD_RHS) {
 +	    base_vector Velem(cvnbdofl);
 +	    for (size_type i = 0; i < cvnbdofl; ++i) Velem[i] = 1E200;
 +	    vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
 +	    return false;
 +	  }
 +	}
 +	
 +	pf_s->interpolation_grad(ctx_y0, coeff, grad, dim_type(N));
 +	
 +	gmm::add(gmm::identity_matrix(), grad);
 +	
 +	gmm::mult(grad, ctx_y0.K(), gradtot);
 +	
 +	std::vector<int> ipvt(N);
 +	size_type info = gmm::lu_factor(gradtot, ipvt);
 +	GMM_ASSERT1(!info, "Singular system, pivot = " << info); // il faudrait faire qlq chose d'autre ... perturber par exemple
 +	gmm::lu_solve(gradtot, ipvt, h, val);
 +	
 +	// line search
 +	bool ok = false;
 +	scalar_type alpha;
 +	for (alpha = 1; alpha >= 1E-5; alpha/=scalar_type(2)) {
 +	  
 +	  ctx_y0.set_xref(y0_ref - alpha*h);
 +	  pf_s->interpolation(ctx_y0, coeff, val, dim_type(N));
 +	  val += ctx_y0.xreal() - x;
 +	  
 +	  if (gmm::vect_norm2(val) < init_res) { ok = true; break; }
 +	}
 +	if (!ok)
 +	  GMM_WARNING1("Line search has failed to invert transformation");
 +	y0_ref -= alpha*h;
 +	ctx_y0.set_xref(y0_ref);
 +	newton_iter++;
 +      }
 +      
 +      base_node y0 = ctx_y0.xreal();
 +      base_node n0_y0 = bgeot::compute_normal(ctx_y0, face_y0);
 +      scalar_type d0_ref = pgt_y0->convex_ref()->is_in_face(face_y0, y0_ref);
 +      scalar_type d0 = d0_ref / gmm::vect_norm2(n0_y0);
 +
 +
 +	
 +
 +      scalar_type d1 = d0_ref; // approximatively a distance to the element
 +      short_type ifd = short_type(-1);
 +
 +      for (short_type k = 0; k <  pgt_y0->structure()->nb_faces(); ++k) {
 +	scalar_type dd = pgt_y0->convex_ref()->is_in_face(k, y0_ref);
 +	if (dd > scalar_type(0) && dd > gmm::abs(d1)) { d1 = dd; ifd = k; }
 +      }
 +      
 +      if (ifd != short_type(-1)) {
 +	d1 /= gmm::vect_norm2(bgeot::compute_normal(ctx_y0, ifd));
 +	if (gmm::abs(d1) < gmm::abs(d0)) d1 = d0;
 +      } else d1 = d0;
 +
 +      
 +//       size_type iptf = m.ind_points_of_face_of_convex(cv_y0, face_y0)[0];
 +//       base_node ptf = x0 - m.points()[iptf];
 +//       scalar_type d2 = gmm::vect_sp(ptf, n0_y0) / gmm::vect_norm2(n0_y0);
 +
 +
 +      
 +      if (noisy) cout << "gmm::vect_norm2(n0_y0) = " << gmm::vect_norm2(n0_y0) << endl;
 +      // Eliminates wrong auto-contact situations
 +      if (noisy) cout << "autocontact status : x0 = " << x0 << " y0 = " << y0 << "  " <<  gmm::vect_dist2(y0, x0) << " : " << d0*0.75 << " : " << d1*0.75 << endl;
 +      if (noisy) cout << "n = " << n << " unit_normal_of_elements[(*it)->id] = " << unit_normal_of_elements[(*it)->id] << endl;
 +
 +
 +
 +      if (d0 < scalar_type(0)
 +	  && ((&(U_y0) == &U
 +	       && (gmm::vect_dist2(y0, x0) < gmm::abs(d1)*scalar_type(3)/scalar_type(4)))
 +	      || gmm::abs(d1) > 0.05)) {
 +	if (noisy)  cout << "Eliminated x0 = " << x0 << " y0 = " << y0
 +			<< " d0 = " << d0 << endl;
 +	continue;
 +      }
 +
 +
 +//       if (d0 < scalar_type(0) && &(U_y0) == &U
 +// 	  && gmm::vect_dist2(y0, x0) < gmm::abs(d1) * scalar_type(2)
 +// 	  && d2 < -ctxu.J() / scalar_type(2)) {
 +// 	/*if (noisy) */ cout << "Eliminated x0 = " << x0 << " y0 = " << y0
 +// 			<< " d0 = " << d0 << endl;
 +// 	continue;
 +//       }
 +      
 +      y0s.push_back(ctx_y0.xreal()); // useful ?
 +      y0_refs.push_back(y0_ref);
 +      elt_nums.push_back((*it)->id);
 +      d0s.push_back(d0);
 +      d1s.push_back(d1);
 +      ctx_y0s.push_back(ctx_y0);
 +      n0_y0 /= gmm::vect_norm2(n0_y0);
 +      n0_y0s.push_back(n0_y0);
 +      
 +      if (noisy) cout << "dist0 = " << d0 << " dist1 = "
 +		      << pgt_y0->convex_ref()->is_in(y0_ref) << endl;
 +    }
 +    
 +    // ----------------------------------------------------------
 +    // Compute the distance to rigid obstacles and selects the
 +    // nearest boundary/obstacle.
 +    // ----------------------------------------------------------
 +    
 +    dim_type state = 0;
 +    scalar_type d0 = 1E100, d1 = 1E100;
 +    base_small_vector grad_obs(N);
 +    
 +    size_type ibound = size_type(-1);
 +    for (size_type k = 0; k < y0_refs.size(); ++k)
 +      if (d1s[k] < d1) { d0 = d0s[k]; d1 = d1s[k]; ibound = k; state = 1; }
 +    
 +    
 +    size_type irigid_obstacle = size_type(-1);
 +#if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
 +    gmm::copy(x, cf.pt_eval);
 +    for (size_type i = 0; i < cf.obstacles.size(); ++i) {
 +      scalar_type d0_o = scalar_type(cf.obstacles_parsers[i].Eval());
 +      if (d0_o < d0) { d0 = d0_o; irigid_obstacle = i; state = 2; }
 +    }
 +    if (state == 2) {
 +      scalar_type EPS = face_factor * 1E-9;
 +      for (size_type k = 0; k < N; ++k) {
 +	cf.pt_eval[k] += EPS;
 +	grad_obs[k] = 
 +	  (scalar_type(cf.obstacles_parsers[irigid_obstacle].Eval())-d0)/EPS;
 +	cf.pt_eval[k] -= EPS;
 +      }
 +    }
 +    
 +#else
 +    if (cf.obstacles.size() > 0)
 +      GMM_WARNING1("Rigid obstacles are ignored. Recompile with "
 +		   "muParser to account for rigid obstacles");
 +#endif
 +    
 +    
 +    // ----------------------------------------------------------
 +    // Print the found contact state ...
 +    // ----------------------------------------------------------
 +    
 +    
 +    if (noisy && state == 1) {
 +      cout  << "Point : " << x0 << " of boundary " << boundary_num
 +	    << " and element " << cv << " state = " << int(state);
 +      if (version & model::BUILD_RHS) cout << " RHS";
 +      if (version & model::BUILD_MATRIX) cout << " MATRIX";
 +    }
 +    if (state == 1) {
 +      size_type nbo = boundary_of_elements[elt_nums[ibound]];
 +      const mesh_fem &mfu_y0 = cf.mfu_of_boundary(nbo);
 +      const mesh &m = mfu_y0.linked_mesh();
 +      size_type icv = ind_of_elements[elt_nums[ibound]];
 +      
 +      if (noisy) cout << " y0 = " << y0s[ibound] << " of element "
 +			    << icv  << " of boundary " << nbo << endl;
 +      for (size_type k = 0; k < m.nb_points_of_convex(icv); ++k)
 +	if (noisy) cout << "point " << k << " : "
 +			<< m.points()[m.ind_points_of_convex(icv)[k]] << endl;
 +      if (nbo == 0 && boundary_num == 0 && d0 < 0.0 && (version & model::BUILD_MATRIX)) GMM_ASSERT1(false, "oups");
 +    }
 +    if (noisy) cout << " d0 = " << d0 << endl;
 +    
 +    
 +    // ----------------------------------------------------------
 +    // Add the contributions to the tangent matrices and rhs
 +    // ----------------------------------------------------------
 +    
 +    GMM_ASSERT1(ctxu.pf()->target_dim() == 1 && ctxl.pf()->target_dim() == 1,
 +		"Large sliding contact assembly procedure has to be adapted "
 +		"to intrinsic vectorial elements. To be done.");
 +    
 +    // �viter les calculs inutiles dans le cas state == 2 ... � voir � la fin
 +    // regarder aussi si on peut factoriser des mat_elem_assembly ...
 +    
 +    base_matrix Melem;
 +    base_vector Velem;
 +    base_tensor tl, tu;
 +    base_small_vector lambda(N), zeta(N), vv(N);
 +    ctxl.base_value(tl);
 +    ctxu.base_value(tu);
 +    
 +    coeff.resize(cvnbdofl);
 +    gmm::copy(gmm::sub_vector
 +	      (L, gmm::sub_index
 +	       (mfl.ind_basic_dof_of_element(cv))), coeff);
 +    ctxl.pf()->interpolation(ctxl, coeff, lambda, dim_type(N));
 +    GMM_ASSERT1(!(std::isnan(lambda[0])), "internal error");
 +
 +    // Tangent term -(1/r)\int \delta\lambda.\mu
 +    if (version & model::BUILD_MATRIX) {
 +      gmm::resize(Melem, cvnbdofl, cvnbdofl); gmm::clear(Melem);
 +      for (size_type i = 0; i < cvnbdofl; ++i)
 +	for (size_type j = 0; j < cvnbdofl; ++j)
 +	  if (i%N == j%N) Melem(i,j) = -tl[i/N]*tl[j/N]*weight/r;
 +      mat_elem_assembly(cf.LL_matrix(boundary_num, boundary_num),
 +			Melem, mfl, cv, mfl, cv);
 +    }
 +    
 +    // Rhs term (1/r)\int (\lambda - P(\zeta)).\mu
 +    // Unstabilized frictionless case for the moment
 +    if (state) gmm::add(lambda, gmm::scaled(n, r*d0), zeta);
 +    if (version & model::BUILD_RHS) {
 +      gmm::clear(vv);
 +      if (state) {
 +	gmm::copy(zeta, vv);
 +	De_Saxce_projection(vv, n, scalar_type(0));
 +	gmm::scale(vv, -scalar_type(1));
 +	gmm::add(lambda, vv);
 +      } else gmm::copy(lambda, vv);
 +      gmm::resize(Velem,  cvnbdofl); gmm::clear(Velem);
 +      for (size_type i = 0; i < cvnbdofl; ++i)
 +	Velem[i] = (tl[i/N] * vv[i%N])*weight/r;
 +      vec_elem_assembly(cf.L_vector(boundary_num), Velem, mfl, cv);
 +    }
 +
 +    if (state) {
 +      base_matrix grad_y0(N, N), gradinv_y0(N, N), gradaux(N,N);
 +      base_vector coeff_y0;
 +      base_small_vector vvv(N), ntilde_y0(N);
 +      base_tensor tgradu, tu_y0, tgradu_y0;
 +      size_type cv_y0 = 0, cvnbdofu_y0 = 0;
 +      size_type boundary_num_y0
 +	= (state == 1) ? boundary_of_elements[elt_nums[ibound]] : 0;
 +      const mesh_fem &mfu_y0
 +	= (state == 1) ? cf.mfu_of_boundary(boundary_num_y0) : mfu;
 +      ctxu.grad_base_value(tgradu);
 +      
 +      if (state == 1) {
 +	cv_y0 = ind_of_elements[elt_nums[ibound]];
 +	cvnbdofu_y0 = mfu_y0.nb_basic_dof_of_element(cv_y0);
 +	const model_real_plain_vector &U_y0
 +	  = cf.disp_of_boundary(boundary_num_y0);
 +	//mesh_fem::ind_dof_ct::const_iterator
 +	//  itdof = mfu_y0.ind_basic_dof_of_element(cv_y0).begin();
 +	coeff_y0.resize(cvnbdofu_y0);
 +	gmm::copy(gmm::sub_vector
 +		  (U_y0, gmm::sub_index
 +		   (mfu_y0.ind_basic_dof_of_element(cv_y0))), coeff_y0);
 +	ctx_y0s[ibound].pf()->interpolation_grad(ctx_y0s[ibound], coeff_y0,
 +						 grad_y0, dim_type(N));
 +	gmm::add(gmm::identity_matrix(), grad_y0);
 +	gmm::copy(grad_y0, gradinv_y0);
 +	gmm::lu_inverse(gradinv_y0);// � proteger contre la non-inversibilit�
 +	ctx_y0s[ibound].base_value(tu_y0);
 +	ctx_y0s[ibound].grad_base_value(tgradu_y0);
 +	gmm::mult(gmm::transposed(gradinv_y0), n0_y0s[ibound], ntilde_y0); // (not unit) normal vector
 +      }
 +      
 +      // Rhs term \int \lambda.(\psi(x_0) - \psi(y_0))
 +      if (version & model::BUILD_RHS) {
 +	gmm::resize(Velem,  cvnbdofu);gmm::clear(Velem);
 +	for (size_type i = 0; i < cvnbdofu; ++i)
 +	  Velem[i] = tu[i/N] * lambda[i%N]*weight;
 +	vec_elem_assembly(cf.U_vector(boundary_num), Velem, mfu, cv);
 +	
 +	if (state == 1) {
 +	  gmm::resize(Velem,  cvnbdofu_y0); gmm::clear(Velem);
 +	  for (size_type i = 0; i < cvnbdofu_y0; ++i)
 +	    Velem[i] = -tu_y0[i/N] * lambda[i%N]*weight;
 +	  vec_elem_assembly(cf.U_vector(boundary_num_y0), Velem, mfu_y0,cv_y0);
 +	}
 +      }	
 +      
 +      if (version & model::BUILD_MATRIX) {
 +	// Tangent term \int (\delta \lambda).(\psi(y_0) - \psi(x_0))
 +	gmm::resize(Melem, cvnbdofu, cvnbdofl); gmm::clear(Melem);
 +	for (size_type i = 0; i < cvnbdofu; ++i)
 +	  for (size_type j = 0; j < cvnbdofl; ++j)
 +	    if (i%N == j%N) Melem(i,j) = -tu[i/N]*tl[j/N]*weight;
 +	mat_elem_assembly(cf.UL_matrix(boundary_num, boundary_num),
 +			  Melem, mfu, cv, mfl, cv);
 +	
 +	if (state == 1) {
 +	  gmm::resize(Melem, cvnbdofu_y0, cvnbdofl); gmm::clear(Melem);
 +	  for (size_type i = 0; i < cvnbdofu_y0; ++i)
 +	    for (size_type j = 0; j < cvnbdofl; ++j)
 +	      if (i%N == j%N) Melem(i,j) = tu_y0[i/N]*tl[j/N]*weight;
 +	  mat_elem_assembly(cf.UL_matrix(boundary_num_y0, boundary_num),
 +			    Melem, mfu_y0, cv_y0, mfl, cv);
 +	}
 +	
 +	// Tangent term \int \lambda.((\nabla \psi(y_0))(I+\nabla u(y_0))^{-1}(\delta u(x_0) - \delta u(y_0)))
 +	if (state == 1) {
 +	  gmm::resize(Melem, cvnbdofu_y0, cvnbdofu); gmm::clear(Melem);
 +	  for (size_type i = 0; i < cvnbdofu_y0; ++i)
 +	    for (size_type j = 0; j < cvnbdofu; ++j)
 +	      for (size_type k = 0; k < N; ++k)
 +		Melem(i, j) += lambda[i%N] * tgradu_y0[i-(i%N)+k]
 +		  * gradinv_y0(k, j%N) * tu[j/N]*weight;
 +	  mat_elem_assembly(cf.UU_matrix(boundary_num_y0, boundary_num),
 +			    Melem, mfu_y0, cv_y0, mfu, cv);
 +	  
 +	  gmm::resize(Melem, cvnbdofu_y0, cvnbdofu_y0); gmm::clear(Melem);
 +	  for (size_type i = 0; i < cvnbdofu_y0; ++i)
 +	    for (size_type j = 0; j < cvnbdofu_y0; ++j)
 +	      for (size_type k = 0; k < N; ++k)
 +		Melem(i, j) -= lambda[i%N] * tgradu_y0[i-(i%N)+k]
 +		  * gradinv_y0(k, j%N) * tu_y0[j/N]*weight;
 +	  mat_elem_assembly(cf.UU_matrix(boundary_num_y0, boundary_num_y0),
 +			    Melem, mfu_y0, cv_y0, mfu_y0, cv_y0);
 +	}
 +	
 +	// Tangent term (1/r)\int \nabla P(zeta) (dzeta/dlambda)(\delta lambda) . \mu
 +	De_Saxce_projection_grad(zeta, n, scalar_type(0), grad);
 +	gmm::resize(Melem, cvnbdofl, cvnbdofl); gmm::clear(Melem);
 +	for (size_type i = 0; i < cvnbdofl; ++i)
 +	  for (size_type j = 0; j < cvnbdofl; ++j)
 +	    Melem(i,j) = tl[i/N]*tl[j/N]*grad(i%N,j%N)*weight/r;
 +	mat_elem_assembly(cf.LL_matrix(boundary_num, boundary_num),
 +			  Melem, mfl, cv, mfl, cv);
 +
 +      
 +	// Tangent term \int (I+\nabla u(y_0))^{-T}\nabla delta(y_0).\delta u(x_0)(\nabla P(zeta) n . \mu)
 +	gmm::mult(grad, n, vv);
 +	gmm::resize(Melem, cvnbdofl, cvnbdofu); gmm::clear(Melem);
 +	for (size_type i = 0; i < cvnbdofl; ++i)
 +	  for (size_type j = 0; j < cvnbdofu; ++j)
 +	    Melem(i, j) = tl[i/N]*vv[i%N]*tu[j/N]
 +	      *((state == 1) ? ntilde_y0[j%N] : grad_obs[j%N])*weight;
 +	mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num),
 +			  Melem, mfl, cv, mfu, cv);
 +	
 +	// Tangent term -\int (I+\nabla u(y_0))^{-T}\nabla delta(y_0).\delta u(y_0)(\nabla P(zeta) n . \mu)
 +	if (state == 1) {
 +	  gmm::resize(Melem, cvnbdofl, cvnbdofu_y0); gmm::clear(Melem);
 +	  for (size_type i = 0; i < cvnbdofl; ++i)
 +	    for (size_type j = 0; j < cvnbdofu_y0; ++j)
 +	      Melem(i, j) = -tl[i/N]*vv[i%N]*tu_y0[j/N]*ntilde_y0[j%N]*weight;
 +	  mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num_y0),
 +			    Melem, mfl, cv, mfu_y0, cv_y0);
 +	}
 +	
 +	// Tangent term \int d_0(\nabla P)(dn/du)(\delta u).\mu
 +	gmm::resize(Melem, cvnbdofl, cvnbdofu); gmm::clear(Melem);
 +	gmm::mult(grad, n, vv);
 +	gmm::mult(gradinv, n, vvv);
 +	gmm::mult(gradinv, gmm::transposed(grad), gradaux);
 +	for (size_type i = 0; i < cvnbdofl; ++i)
 +	  for (size_type j = 0; j < cvnbdofu; ++j)
 +	    for (size_type k = 0; k < N; ++k)
 +	      Melem(i,j) += d0*tl[i/N]*vv[i%N]
 +		*tgradu[j-(j%N)+k]*n[j%N]*vvv[k]*weight;
 +	for (size_type i = 0; i < cvnbdofl; ++i)
 +	  for (size_type j = 0; j < cvnbdofu; ++j)
 +	    for (size_type k = 0; k < N; ++k)
 +	      Melem(i,j) -= d0*tl[i/N]*gradaux(k,i%N)*tgradu[j-(j%N)+k]
 +		*n[j%N]*weight;
 +
 +	
 +	
 +	// Tangent term (1/r)\int \nabla_n P(zeta) (dn/du)(\delta u) . \mu
 +	// On peut certainement factoriser d'avantage ce terme avec le
 +	// pr�c�dent. Attendre la version avec frottement.
 +	De_Saxce_projection_gradn(zeta, n, scalar_type(0), grad);
 +	gmm::mult(gradinv, gmm::transposed(grad), gradaux);
 +	gmm::mult(grad, n, vv);
 +	gmm::mult(gradinv, n, vvv);
 +	// gmm::resize(Melem, cvnbdofl, cvnbdofu); gmm::clear(Melem);factorised
 +	for (size_type i = 0; i < cvnbdofl; ++i)
 +	  for (size_type j = 0; j < cvnbdofu; ++j)
 +	    for (size_type k = 0; k < N; ++k)
 +	      Melem(i,j) += tl[i/N]*vv[i%N]
 +		*tgradu[j-(j%N)+k]*n[j%N]*vvv[k]*weight/r;
 +	for (size_type i = 0; i < cvnbdofl; ++i)
 +	  for (size_type j = 0; j < cvnbdofu; ++j)
 +	    for (size_type k = 0; k < N; ++k)
 +	      Melem(i,j) -= tl[i/N]*gradaux(k,i%N)*tgradu[j-(j%N)+k]
 +		*n[j%N]*weight/r;
 +	mat_elem_assembly(cf.LU_matrix(boundary_num, boundary_num),
 +			  Melem, mfl, cv, mfu, cv);
 +      }
 +    }
 +    return true;
 +  }
 +
 +  //=========================================================================
 +  // 3)- Large sliding contact brick
 +  //=========================================================================
 +
 +  struct integral_large_sliding_contact_brick : public virtual_brick {
 +
 +    
 +    struct contact_boundary {
 +      size_type region;
 +      std::string varname;
 +      std::string multname;
 +      const mesh_im *mim;
 +    };
 +
 +    std::vector<contact_boundary> boundaries;
 +    std::vector<std::string> obstacles;
 +
 +    void add_boundary(const std::string &varn, const std::string &multn,
 +		      const mesh_im &mim, size_type region) {
 +      contact_boundary cb;
 +      cb.region = region; cb.varname = varn; cb.multname = multn; cb.mim=&mim;
 +      boundaries.push_back(cb);
 +    }
 +
 +    void add_obstacle(const std::string &obs) 
 +    { obstacles.push_back(obs); }
 +
 +    void build_contact_frame(const model &md, contact_frame &cf) const {
 +      for (size_type i = 0; i < boundaries.size(); ++i) {
 +	const contact_boundary &cb = boundaries[i];
 +	cf.add_boundary(md.mesh_fem_of_variable(cb.varname),
 +			md.real_variable(cb.varname),
 +			md.mesh_fem_of_variable(cb.multname),
 +			md.real_variable(cb.multname), cb.region);
 +      }
 +      for (size_type i = 0; i < obstacles.size(); ++i)
 +	cf.add_obstacle(obstacles[i]);
 +    }
 +
++=======
+    const std::string &dataname_obs, const std::string &dataname_gamma0,
+    scalar_type theta,
+    const std::string &dataname_friction_coeff,
+    const std::string &dataname_alpha,
+    const std::string &dataname_wt,
+    size_type region) {
  
-     virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
-                                         const model::varnamelist &vl,
-                                         const model::varnamelist &dl,
-                                         const model::mimlist &mims,
-                                         model::real_matlist &matl,
-                                         model::real_veclist &vecl,
-                                         model::real_veclist &,
-                                         size_type region,
-                                         build_version version) const;
+     bool nofriction = (dataname_friction_coeff.size() == 0);
+     pbrick pbr = new Nitsche_contact_rigid_obstacle_brick(theta, nofriction);
  
-     integral_large_sliding_contact_brick() {
-       set_flags("Integral large sliding contact brick",
-                 false /* is linear*/, false /* is symmetric */,
-                 false /* is coercive */, true /* is real */,
-                 false /* is complex */);
+     bool co = (theta == scalar_type(1)) && nofriction;
+     model::termlist tl;
+     tl.push_back(model::term_description(varname_u, varname_u, co));
+ 
+     model::varnamelist dl(1, dataname_obs);
+     dl.push_back(dataname_gamma0);
+     if (!nofriction) dl.push_back(dataname_friction_coeff);
+     if (dataname_alpha.size() > 0) {
+       dl.push_back(dataname_alpha);
+       if (dataname_wt.size() > 0) dl.push_back(dataname_wt);
      }
  
-   };
+     model::varnamelist vl(1, varname_u);
  
+     std::vector<std::string> aux_vars;
+     md.auxilliary_variables_of_Neumann_terms(varname_u, aux_vars);
+     for (size_type i = 0; i < aux_vars.size(); ++i) {
+       vl.push_back(aux_vars[i]);
+       tl.push_back(model::term_description(varname_u, aux_vars[i], false));
+     }
  
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+   }
  
  
-   void integral_large_sliding_contact_brick::asm_real_tangent_terms
-   (const model &md, size_type /* ib */, const model::varnamelist &vl,
-    const model::varnamelist &dl, const model::mimlist &/* mims */,
-    model::real_matlist &matl, model::real_veclist &vecl,
-    model::real_veclist &, size_type /* region */,
-    build_version version) const {
  
-     fem_precomp_pool fppool;
-     base_matrix G;
-     size_type N = md.mesh_fem_of_variable(vl[0]).linked_mesh().dim();
-     contact_frame cf(N);
-     build_contact_frame(md, cf);
-     
-     size_type Nvar = vl.size(), Nu = cf.Urhs.size(), Nl = cf.Lrhs.size();
-     GMM_ASSERT1(Nvar == Nu+Nl, "Wrong size of variable list for integral "
- 		"large sliding contact brick");
-     GMM_ASSERT1(matl.size() == Nvar*Nvar, "Wrong size of terms for "
- 		"integral large sliding contact brick");
-     
-     if (version & model::BUILD_MATRIX) {
-       for (size_type i = 0; i < Nvar; ++i)
- 	for (size_type j = 0; j < Nvar; ++j) {
- 	  gmm::clear(matl[i*Nvar+j]);
- 	  if (i <  Nu && j <  Nu) cf.UU(i,j)       = &(matl[i*Nvar+j]);
- 	  if (i >= Nu && j <  Nu) cf.LU(i-Nu,j)    = &(matl[i*Nvar+j]);
- 	  if (i <  Nu && j >= Nu) cf.UL(i,j-Nu)    = &(matl[i*Nvar+j]);
- 	  if (i >= Nu && j >= Nu) cf.LL(i-Nu,j-Nu) = &(matl[i*Nvar+j]);
- 	}
-     }
-     if (version & model::BUILD_RHS) {
-       for (size_type i = 0; i < vl.size(); ++i) {
- 	if (i < Nu) cf.Urhs[i] = &(vecl[i*Nvar]);
- 	else cf.Lrhs[i-Nu] = &(vecl[i*Nvar]);
-       }
-     }
-     
-     // Data : r, [friction_coeff,]
-     GMM_ASSERT1(dl.size() == 2, "Wrong number of data for integral large "
- 		"sliding contact brick");
-     
-     const model_real_plain_vector &vr = md.real_variable(dl[0]);
-     GMM_ASSERT1(gmm::vect_size(vr) == 1, "Parameter r should be a scalar");
-     
-     const model_real_plain_vector &f_coeff = md.real_variable(dl[1]);
-     GMM_ASSERT1(gmm::vect_size(f_coeff) == 1,
- 		"Friction coefficient should be a scalar");
-     
-     contact_elements ce(cf);
-     ce.init();
-     
-     for (size_type bnum = 0; bnum < boundaries.size(); ++bnum) {
-       mesh_region rg(boundaries[bnum].region);
-       const mesh_fem &mfu=md.mesh_fem_of_variable(boundaries[bnum].varname);
-       const mesh_fem &mfl=md.mesh_fem_of_variable(boundaries[bnum].multname);
-       const mesh_im &mim = *(boundaries[bnum].mim);
-       const mesh &m = mfu.linked_mesh();
-       mfu.linked_mesh().intersect_with_mpi_region(rg);
-       
-       for (getfem::mr_visitor v(rg, m); !v.finished(); ++v) {
- 	// cout << "boundary " << bnum << " element " << v.cv() << endl;
- 	size_type cv = v.cv();
- 	bgeot::pgeometric_trans pgt = m.trans_of_convex(cv);
- 	pfem pf_s = mfu.fem_of_element(cv);
- 	pfem pf_sl = mfl.fem_of_element(cv);
- 	pintegration_method pim = mim.int_method_of_element(cv);
- 	bgeot::vectors_to_base_matrix(G, m.points_of_convex(cv));
- 	
- 	pfem_precomp pfpu
- 	  = fppool(pf_s,&(pim->approx_method()->integration_points()));
- 	pfem_precomp pfpl
- 	  = fppool(pf_sl,&(pim->approx_method()->integration_points()));
- 	fem_interpolation_context ctxu(pgt,pfpu,size_type(-1), G, cv, v.f());
- 	fem_interpolation_context ctxl(pgt,pfpl,size_type(-1), G, cv, v.f());
- 	
- 	for (size_type k = 0;
- 	     k < pim->approx_method()->nb_points_on_face(v.f()); ++k) {
- 	  size_type ind
- 	    = pim->approx_method()->ind_first_point_on_face(v.f()) + k;
- 	  ctxu.set_ii(ind);
- 	  ctxl.set_ii(ind);
- 	  if (!(ce.add_point_contribution
- 	       (bnum, ctxu, ctxl,pim->approx_method()->coeff(ind),
- 		f_coeff[0], vr[0], version))) return;
- 	}
-       }
-     }
-   }
-   
  
-   // r ne peut pas �tre variable pour le moment.
-   // dataname_friction_coeff ne peut pas �tre variable non plus ...
+ #ifdef EXPERIMENTAL_PURPOSE_ONLY
  
-   size_type add_integral_large_sliding_contact_brick
-   (model &md, const mesh_im &mim, const std::string &varname_u,
-    const std::string &multname, const std::string &dataname_r,
-    const std::string &dataname_friction_coeff, size_type region) {
  
-     integral_large_sliding_contact_brick *pbr
-       = new integral_large_sliding_contact_brick();
-     
-     pbr->add_boundary(varname_u, multname, mim, region);
+   //=========================================================================
+   //
+   //  Contact condition with a rigid obstacle : generic Nitsche's method
+   //  Experimental for midpoint scheme
+   //
+   //=========================================================================
  
-     model::termlist tl;
-     tl.push_back(model::term_description(varname_u, varname_u, false));
-     tl.push_back(model::term_description(varname_u, multname,  false));
-     tl.push_back(model::term_description(multname,  varname_u, false));
-     tl.push_back(model::term_description(multname,  multname,  false));
+ 
+   class contact_nitsche_nonlinear_term_midpoint : public nonlinear_elem_term {
+     // Option:
+     // 1 : rhs term
+     // 2 : tangent term in main unknown (u)
+     // 3 : tangent term in auxilliary variable (p)
+ 
+   protected:
+     base_small_vector u;      // tangential relative displacement
+     scalar_type un, wn;       // normal relative displacement (positive when
+                                //  the first elas. body surface moves outwards)
+     base_small_vector no, n;   // surface normal, pointing outwards with
+                                // respect to the (first) elastic body
+     scalar_type g, f_coeff;    // gap and friction coefficient
+ 
+     base_small_vector aux1, wt, V, Pr, pgg, zeta;
+     base_matrix GPr, grad;
+     base_vector coeff;
+     const model *md;
+     const std::string *varname;
+     const std::string *auxvarname;
+     const mesh_fem &mf_u;       // mandatory
+     const mesh_fem &mf_obs;     // mandatory
+     const mesh_fem *pmf_coeff;
+     const mesh_fem *mf_p;
+     base_vector U, obs, friction_coeff, WT, UPLUSWT;
+     dim_type N;
+     size_type option;
+     scalar_type gamma, gamma0, theta, alpha;
+     base_tensor tG, tp, tpp, tbv, tpaux;
+     mutable bgeot::multi_index sizes_;
+     size_type option_midpoint;
+ 
+     void adjust_tensor_size(void) {
+       sizes_.resize(1); sizes_[0] = N;
+       tG.adjust_sizes(sizes_);
+       sizes_.resize(2); sizes_[0] = sizes_[1] = 1;
+       switch (option) {
+       case 1 : sizes_.resize(1); break;
+       case 2 : case 3 :  break;
+       }
+       gmm::resize(grad, 1, N);
+       u.resize(N); no.resize(N); n.resize(N);
+       aux1.resize(1); wt.resize(N); V.resize(N); zeta.resize(N);
+       gmm::resize(GPr, N, N); gmm::resize(Pr, N); gmm::resize(pgg, N);
+     }
+ 
+   public:
+     const bgeot::multi_index &sizes(size_type cv) const {
+       if (cv != size_type(-1))
+         switch(option) {
+         case 1:
+           sizes_[0] = short_type(mf_u.nb_basic_dof_of_element(cv));
+           break;
+         case 2:
+           sizes_[0] = sizes_[1]= short_type(mf_u.nb_basic_dof_of_element(cv));
+           break;
+         case 3:
+           sizes_[0] = short_type(mf_u.nb_basic_dof_of_element(cv));
+           sizes_[1] = short_type(mf_p->nb_basic_dof_of_element(cv));
+           break;
+         }
+       return sizes_;
+     }
+ 
+ 
+     contact_nitsche_nonlinear_term_midpoint
+       (size_type option_, scalar_type gamma0_, scalar_type theta_,
+        scalar_type alpha_, const model &md_, const std::string &varname_,
+        const mesh_fem &mf_u_, const model_real_plain_vector &U_,
+        const mesh_fem &mf_obs_,
+        const model_real_plain_vector &obs_,
+        const std::string &auxvarname_,
+        const mesh_fem *pmf_p_ = 0,
+        const mesh_fem *pmf_coeff_ = 0,
+        const model_real_plain_vector *f_coeff_ = 0,
+        const model_real_plain_vector *WT_ = 0, size_type option_midpoint_ = 1)
+       : md(&md_), varname(&varname_), auxvarname(&auxvarname_),
+         mf_u(mf_u_), mf_obs(mf_obs_),
+         pmf_coeff(pmf_coeff_), mf_p(pmf_p_), U(mf_u.nb_basic_dof()),
+         obs(mf_obs.nb_basic_dof()),
+         friction_coeff(0), option(option_),
+         gamma0(gamma0_), theta(theta_), alpha(alpha_),
+         option_midpoint(option_midpoint_) {
+       N = mf_u_.linked_mesh().dim();
+       adjust_tensor_size();
+ 
+       mf_u.extend_vector(U_, U);
+       mf_obs.extend_vector(obs_, obs);
+ 
+       if (!pmf_coeff)
+         if (f_coeff_) f_coeff = (*f_coeff_)[0]; else f_coeff = scalar_type(0);
+       else {
+         friction_coeff.resize(pmf_coeff->nb_basic_dof());
+         pmf_coeff->extend_vector(*f_coeff_, friction_coeff);
+       }
+       if (WT_) {
+         WT.resize(mf_u.nb_basic_dof());
+         mf_u_.extend_vector(*WT_, WT);
+         UPLUSWT.resize(mf_u.nb_basic_dof());
+         gmm::add(U, gmm::scaled(WT, -scalar_type(1)/scalar_type(2)), UPLUSWT);
+       }
+     }
+ 
+ 
+     void compute(fem_interpolation_context &ctx, bgeot::base_tensor &t) {
+ 
+       md->compute_Neumann_terms(1, *varname, mf_u, WT, ctx, n, tG);
+ 
+       scalar_type Pw = wn - gamma * gmm::vect_sp(tG.as_vector(), no);
+       cout << "Pw = " << Pw << endl;
+ 
+ 
+       if (option_midpoint == 2)
+         md->compute_Neumann_terms(1, *varname, mf_u, UPLUSWT, ctx, n, tG);
+       else
+         md->compute_Neumann_terms(1, *varname, mf_u, U, ctx, n, tG);
+       for (size_type i = 0; i < N; ++i)
+         if (option_midpoint == 2)
+           zeta[i] = tG[i]
+             + ((g-un+wn/scalar_type(2)+alpha*(un-wn/scalar_type(2))) * no[i]
+                + alpha*wt[i] - alpha*u[i] ) / gamma;
+         else
+           zeta[i] = tG[i]
+             + ((g-un+alpha*un) * no[i] + alpha*wt[i] - alpha*u[i] ) / gamma;
+ 
+       if (option_midpoint == 2)
+         md->compute_Neumann_terms(1, *varname, mf_u, U, ctx, n, tG);
+ 
+       if ((option == 1) || (theta != scalar_type(0))) {
+         coupled_projection(zeta, no, f_coeff, Pr);
+         gmm::add(Pr, gmm::scaled(tG.as_vector(), -scalar_type(1)), pgg);
+       }
+ 
+       switch (option) {
+       case 1:
+         {
+           ctx.pf()->real_base_value(ctx, tbv);
+           size_type qmult = N / ctx.pf()->target_dim();
+           short_type nbdofu = sizes_[0];
+           if (theta != scalar_type(0)) {
+             sizes_.resize(2);
+             sizes_[1] = N;
+             tp.adjust_sizes(sizes_);
+             sizes_.resize(1);
+             md->compute_Neumann_terms(2, *varname, mf_u, U, ctx, n, tp);
+           }
+           for (size_type i = 0; i < nbdofu; ++i) {
+             t[i] = scalar_type(0);
+             for (size_type j = 0; j < N; ++j) {
+               if (theta != scalar_type(0))
+                 t[i] -= gamma*pgg[j]*theta*tp(i,j);
+               if (qmult == 1) t[i] += Pr[j]*tbv(i,j);
+             }
+             if (qmult > 1) t[i] += Pr[i%N] * tbv(i/N,0);
+           }
+         }
+         break;
+ 
+       case 2:
+         {
+           short_type nbdofu = sizes_[1];
+           sizes_[1] = N;
+           tp.adjust_sizes(sizes_);
+           sizes_[1] = nbdofu;
+           if (option_midpoint == 2)
+             md->compute_Neumann_terms(2, *varname, mf_u, U, ctx, n, tp);
+           else
+             md->compute_Neumann_terms(2, *varname, mf_u, UPLUSWT, ctx, n, tp);
+           if (theta != scalar_type(0)) {
+             sizes_.resize(3); sizes_[2] = N;
+             tpp.adjust_sizes(sizes_);
+             sizes_.resize(2);
+             if (option_midpoint == 1)
+               md->compute_Neumann_terms(3, *varname, mf_u, UPLUSWT, ctx,n,tpp);
+             else
+               md->compute_Neumann_terms(3, *varname, mf_u, U, ctx, n, tpp);
+           }
+ 
+           ctx.pf()->real_base_value(ctx, tbv);
+           size_type qmult = N / ctx.pf()->target_dim();
+           coupled_projection_grad(zeta, no, f_coeff, GPr);
+ 
+           for (size_type i = 0; i < nbdofu; ++i)
+             for (size_type j = 0; j < nbdofu; ++j) {
+               scalar_type res(0);
+               for (size_type k = 0; k < N; ++k) {
+                 if (theta != scalar_type(0))
+                   res -= gamma * theta * tp(i,k) * tp(j,k);
+                 scalar_type tbvvi(0), tbvvjn(0);
+                 if (qmult == 1) {
+                   tbvvi = tbv(i,k);
+                   for (size_type l = 0; l < N; ++l) tbvvjn += no[l]*tbv(j,l);
+                 } else {
+                   tbvvi = ((i%N)==k) ? tbv(i/N,0) : scalar_type(0);
+                   tbvvjn = no[j%N]*tbv(j/N,0);
+                 }
+                 for (size_type l = 0; l < N; ++l) {
+                   scalar_type tbvvj(0);
+                   if (qmult == 1)
+                     tbvvj = tbv(j,l);
+                   else
+                     tbvvj=(((j%N)==l) ? tbv(j/N,0):scalar_type(0));
+                   res += GPr(k,l)
+                     * (gamma*tp(j,l) - alpha*tbvvj
+                        - (scalar_type(1)-alpha)*no[l]*tbvvjn)
+                     * (theta * tp(i,k) - tbvvi/gamma);
+                 }
+ 
+                 if (theta != scalar_type(0))
+                   res += theta*gamma*pgg[k] * tpp(i,j,k);
+               }
+               t(i,j) = res;
+             }
+         }
+         break;
+ 
+       case 3:
+         {
+           short_type nbdofu = sizes_[0];
+           short_type nbdofp = sizes_[1];
+           sizes_[0] = nbdofp; sizes_[1] = N;
+           tpaux.adjust_sizes(sizes_);
+           sizes_[0] = nbdofu; sizes_[1] = nbdofp;
+           if (option_midpoint == 2)
+             md->compute_auxilliary_Neumann_terms(2, *varname, mf_u, UPLUSWT,
+                                                  *auxvarname, ctx, n, tpaux);
+           else
+             md->compute_auxilliary_Neumann_terms(2, *varname, mf_u, U,
+                                                  *auxvarname, ctx, n, tpaux);
+ 
+           if (theta != scalar_type(0)) {
+             sizes_[1] = N;
+             tp.adjust_sizes(sizes_);
+             sizes_[1] = nbdofp;
+             if (option_midpoint == 2)
+               md->compute_Neumann_terms(2, *varname, mf_u, UPLUSWT, ctx, n,tp);
+             else
+               md->compute_Neumann_terms(2, *varname, mf_u, U, ctx, n, tp);
+             sizes_.resize(3); sizes_[2] = N;
+             tpp.adjust_sizes(sizes_);
+             sizes_.resize(2);
+             if (option_midpoint == 2)
+               md->compute_auxilliary_Neumann_terms(3, *varname, mf_u, UPLUSWT,
+                                                    *auxvarname, ctx, n, tpp);
+             else
+               md->compute_auxilliary_Neumann_terms(3, *varname, mf_u, U,
+                                                    *auxvarname, ctx, n, tpp);
+           }
+ 
+           ctx.pf()->real_base_value(ctx, tbv);
+           size_type qmult = N / ctx.pf()->target_dim();
+           coupled_projection_grad(zeta, no, f_coeff, GPr);
+ 
+           for (size_type i = 0; i < nbdofu; ++i)
+             for (size_type j = 0; j < nbdofp; ++j) {
+               scalar_type res(0);
+               for (size_type k = 0; k < N; ++k) {
+                 if (theta != scalar_type(0))
+                   res -= gamma * theta * tp(i,k) * tpaux(j,k);
+                 scalar_type gttpik(0), tbvvi(0);
+                 if (theta != scalar_type(0)) gttpik = gamma*theta*tp(i,k);
+                 if (qmult == 1) tbvvi = tbv(i,k);
+                 else tbvvi=(((i%N)==k) ? tbv(i/N,0):scalar_type(0));
+                 for (size_type l = 0; l < N; ++l)
+                   res += GPr(k,l) * tpaux(j,l) * (gttpik - tbvvi);
+                 if (theta != scalar_type(0))
+                   res += theta*gamma*pgg[k] * tpp(i,j,k);
+               }
+               t(i,j) = res;
+             }
+         }
+         break;
+ 
+       default : GMM_ASSERT1(false, "Invalid option");
+       }
+ 
+       switch (option_midpoint) {
+       case 1:
+         gmm::scale(t.as_vector(), gmm::Heaviside(Pw));
+         break;
+       case 2:
+         gmm::scale(t.as_vector(),
+                    (scalar_type(1) - gmm::Heaviside(Pw)));
+         break;
+       default:
+         GMM_ASSERT1(false, "Wrong option");
+       }
+ 
+     }
+ 
+ 
+     void prepare(fem_interpolation_context& ctx, size_type nb) {
+ 
+       size_type cv = ctx.convex_num();
+ 
+       switch (nb) { // last is computed first
+       case 1 : // calculate [u] and [un] interpolating [U] and [WT] on [mf_u]
+         slice_vector_on_basic_dof_of_element(mf_u, U, cv, coeff);
+         ctx.pf()->interpolation(ctx, coeff, u, N);
+         un = gmm::vect_sp(u, no);
+         if (gmm::vect_size(WT) == gmm::vect_size(U)) {
+           slice_vector_on_basic_dof_of_element(mf_u, WT, cv, coeff);
+           ctx.pf()->interpolation(ctx, coeff, wt, N);
+           wn = gmm::vect_sp(wt, no);
+           wt -= gmm::vect_sp(wt, no) * no;
+         }
+         // computation of h for gamma = gamma0*h
+         scalar_type emax, emin; gmm::condition_number(ctx.K(),emax,emin);
+         gamma = gamma0 * emax * sqrt(scalar_type(N));
+         break;
+ 
+       case 2 : // calculate [g], [n] and [no] interpolating [obs] on [mf_obs]
+         slice_vector_on_basic_dof_of_element(mf_obs, obs, cv, coeff);
+         ctx.pf()->interpolation_grad(ctx, coeff, grad, 1);
+         gmm::copy(gmm::mat_row(grad, 0), no);
+         no /= -gmm::vect_norm2(no);
+         ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+         g = aux1[0];
+         n = bgeot::compute_normal(ctx, ctx.face_num());
+         n /= gmm::vect_norm2(n);
+         break;
+ 
+       case 3 : // calculate [f_coeff] interpolating [friction_coeff] on [mf_coeff]
+         if (pmf_coeff) {
+           slice_vector_on_basic_dof_of_element(*pmf_coeff, friction_coeff, cv, coeff);
+           ctx.pf()->interpolation(ctx, coeff, aux1, 1);
+           f_coeff = aux1[0];
+         }
+         break;
+ 
+       default : GMM_ASSERT1(false, "Invalid option");
+       }
+     }
+   };
+ 
+ 
+ 
+   void asm_Nitsche_contact_rigid_obstacle_rhs_midpoint
+     (model_real_plain_vector &R, const mesh_im &mim, const model &md,
+      const std::string &varname,
+      const getfem::mesh_fem &mf_u, const model_real_plain_vector &U,
+      const getfem::mesh_fem &mf_obs, const model_real_plain_vector &obs,
+      const getfem::mesh_fem *pmf_coeff, const model_real_plain_vector *f_coeff,
+      const model_real_plain_vector *WT,
+      scalar_type gamma0, scalar_type theta, scalar_type alpha,
+      const mesh_region &rg, size_type option) {
+ 
+     contact_nitsche_nonlinear_term_midpoint
+       nterm(1, gamma0, theta, alpha, md, varname, mf_u, U, mf_obs,
+             obs, "", 0, pmf_coeff, f_coeff, WT, option);
+ 
+     const std::string aux_fems = pmf_coeff ? "#1,#2,#3" : "#1,#2";
+ 
+     getfem::generic_assembly assem("V(#1)+=comp(NonLin$1(#1,"+aux_fems+"));");
+ 
+     assem.push_mi(mim);
+     assem.push_mf(mf_u);
+     assem.push_mf(mf_obs);
+     if (pmf_coeff) assem.push_mf(*pmf_coeff);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_vec(R);
+     assem.assembly(rg);
+   }
+ 
+ 
+   template<typename MAT>
+   void asm_Nitsche_contact_rigid_obstacle_tangent_matrix_midpoint
+   (MAT &K, const mesh_im &mim, const model &md, const std::string &varname,
+    const getfem::mesh_fem &mf_u, const model_real_plain_vector &U,
+    const getfem::mesh_fem &mf_obs, const model_real_plain_vector &obs,
+    const getfem::mesh_fem *pmf_coeff, const model_real_plain_vector *f_coeff,
+    const model_real_plain_vector *WT,
+    scalar_type gamma0, scalar_type theta, scalar_type alpha,
+    const mesh_region &rg, size_type option) {
+ 
+     contact_nitsche_nonlinear_term_midpoint
+       nterm(2, gamma0, theta, alpha, md, varname, mf_u, U, mf_obs,
+             obs, "", 0, pmf_coeff, f_coeff, WT, option);
+ 
+     const std::string aux_fems = pmf_coeff ? "#1,#2,#3" : "#1,#2";
+ 
+     getfem::generic_assembly
+       assem("M(#1,#1)+=comp(NonLin$1(#1,"+aux_fems+"));");
+ 
+     assem.push_mi(mim);
+     assem.push_mf(mf_u);
+     assem.push_mf(mf_obs);
+     if (pmf_coeff) assem.push_mf(*pmf_coeff);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_mat(K);
+     assem.assembly(rg);
+   }
+ 
+   template<typename MAT>
+   void asm_Nitsche_contact_rigid_obstacle_tangent_matrix_auxilliary_midpoint
+   (MAT &K, const mesh_im &mim, const model &md, const std::string &varname,
+    const getfem::mesh_fem &mf_u, const model_real_plain_vector &U,
+    const getfem::mesh_fem &mf_obs, const model_real_plain_vector &obs,
+    const getfem::mesh_fem *pmf_coeff, const model_real_plain_vector *f_coeff,
+    const model_real_plain_vector *WT,
+    scalar_type gamma0, scalar_type theta, scalar_type alpha,
+    const std::string &auxvarname, const getfem::mesh_fem &mf_p,
+    const mesh_region &rg, size_type option) {
+ 
+     contact_nitsche_nonlinear_term_midpoint
+       nterm(3, gamma0, theta, alpha, md, varname, mf_u, U, mf_obs,
+             obs, auxvarname, &mf_p, pmf_coeff, f_coeff, WT, option);
+ 
+     const std::string aux_fems = pmf_coeff ? "#1,#2,#3" : "#1,#2";
+     const std::string p_fem = pmf_coeff ? "#4" : "#3";
+ 
+     getfem::generic_assembly
+       assem("M(#1,"+p_fem+")+=comp(NonLin$1(#1,"+aux_fems+"));");
+ 
+     assem.push_mi(mim);
+     assem.push_mf(mf_u);
+     assem.push_mf(mf_obs);
+     if (pmf_coeff) assem.push_mf(*pmf_coeff);
+     assem.push_mf(mf_p);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_mat(K);
+     assem.assembly(rg);
+   }
+ 
+ 
+   struct Nitsche_midpoint_contact_rigid_obstacle_brick : public virtual_brick {
+ 
+     scalar_type theta;
+     bool contact_only;
+     size_type option;
+ 
+     virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
+                                         const model::varnamelist &vl,
+                                         const model::varnamelist &dl,
+                                         const model::mimlist &mims,
+                                         model::real_matlist &matl,
+                                         model::real_veclist &vecl,
+                                         model::real_veclist &,
+                                         size_type region,
+                                         build_version version) const {
+ 
+       // Integration method
+       GMM_ASSERT1(mims.size() == 1, "Nitsche contact with rigid obstacle "
+                   "bricks need a single mesh_im");
+       const mesh_im &mim = *mims[0];
+ 
+ 
+       const model_real_plain_vector &u = md.real_variable(vl[0]);
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+ 
+       // Data : obs, r, theta, [alpha,] [WT]
+       GMM_ASSERT1(dl.size() >= (contact_only ? 2:3),
+                   "Wrong number of data for Nitsche "
+                   "contact with rigid obstacle brick");
+ 
+       const model_real_plain_vector &obs = md.real_variable(dl[0]);
+       const mesh_fem &mf_obs = md.mesh_fem_of_variable(dl[0]);
+       size_type sl = gmm::vect_size(obs) * mf_obs.get_qdim() / mf_obs.nb_dof();
+       GMM_ASSERT1(sl == 1, "the data corresponding to the obstacle has not "
+                   "the right format");
+ 
+       const model_real_plain_vector &vgamma0 = md.real_variable(dl[1]);
+       GMM_ASSERT1(gmm::vect_size(vgamma0) == 1,
+                   "Parameter gamma0 should be a scalar");
+       scalar_type gamma0 = vgamma0[0];
+ 
+       const model_real_plain_vector *f_coeff = 0;
+       const mesh_fem *pmf_coeff = 0;
+ 
+       if (!contact_only) {
+         f_coeff = &(md.real_variable(dl[2]));
+         pmf_coeff = md.pmesh_fem_of_variable(dl[2]);
+         sl = gmm::vect_size(*f_coeff);
+         if (pmf_coeff)
+           { sl*= pmf_coeff->get_qdim(); sl /= pmf_coeff->nb_dof(); }
+         GMM_ASSERT1(sl == 1, "the data corresponding to the friction "
+                     "coefficient has not the right format");
+       }
+ 
+       scalar_type alpha = 1;
+       if (!contact_only && dl.size() >= 4) {
+         GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[3])) == 1,
+                     "Parameter alpha should be a scalar");
+         alpha = md.real_variable(dl[3])[0];
+       }
+ 
+       const model_real_plain_vector *WT
+         = (dl.size()>=5) ? &(md.real_variable(dl[4])) : 0;
+ 
+       GMM_ASSERT1(matl.size() == vl.size(), "Wrong number of terms for "
+                   "Nitsche contact with rigid obstacle brick");
+ 
+ 
+       mesh_region rg(region);
+       mf_u.linked_mesh().intersect_with_mpi_region(rg);
+ 
+       if (version & model::BUILD_MATRIX) {
+         GMM_TRACE2("Nitsche contact with rigid obstacle tangent term");
+         gmm::clear(matl[0]);
+         asm_Nitsche_contact_rigid_obstacle_tangent_matrix_midpoint
+           (matl[0], mim, md, vl[0], mf_u, u, mf_obs, obs,  pmf_coeff,
+            f_coeff, WT, gamma0, theta, alpha, rg, option);
+ 
+         for (size_type i = 1; i < vl.size(); ++i) { // Auxilliary variables
+           gmm::clear(matl[i]);
+           asm_Nitsche_contact_rigid_obstacle_tangent_matrix_auxilliary_midpoint
+             (matl[i], mim, md, vl[0], mf_u, u, mf_obs, obs, pmf_coeff,
+              f_coeff, WT, gamma0, theta, alpha, vl[i],
+              md.mesh_fem_of_variable(vl[i]), rg, option);
+         }
+       }
+ 
+       if (version & model::BUILD_RHS) {
+         gmm::clear(vecl[0]);
+         asm_Nitsche_contact_rigid_obstacle_rhs_midpoint
+           (vecl[0], mim, md, vl[0], mf_u, u, mf_obs, obs,  pmf_coeff,
+            f_coeff, WT, gamma0, theta, alpha, rg, option);
+       }
+     }
+ 
+     Nitsche_midpoint_contact_rigid_obstacle_brick(scalar_type theta_, bool nofriction, size_type option_) {
+       theta = theta_;
+       contact_only = nofriction;
+       option = option_;
+       bool co = (theta_ == scalar_type(1)) && nofriction;
+       set_flags("Integral Nitsche contact and friction with rigid "
+                 "obstacle brick",
+                 false /* is linear*/, co /* is symmetric */,
+                 co /* is coercive */, true /* is real */,
+                 false /* is complex */, false /* compute each time */,
+                 false /* has a Neumann term */);
+     }
+ 
+   };
+ 
+ 
+   size_type add_Nitsche_midpoint_contact_with_rigid_obstacle_brick
+   (model &md, const mesh_im &mim, const std::string &varname_u,
+    const std::string &dataname_obs, const std::string &dataname_gamma0,
+    scalar_type theta,
+    const std::string &dataname_friction_coeff,
+    const std::string &dataname_alpha,
+    const std::string &dataname_wt,
+    size_type region, size_type option) {
+ 
+     bool nofriction = (dataname_friction_coeff.size() == 0);
+     pbrick pbr = new Nitsche_midpoint_contact_rigid_obstacle_brick(theta, nofriction, option);
+ 
+     bool co = (theta == scalar_type(1)) && nofriction;
+     model::termlist tl;
+     tl.push_back(model::term_description(varname_u, varname_u, co));
+ 
+     model::varnamelist dl(1, dataname_obs);
+     dl.push_back(dataname_gamma0);
+     if (!nofriction) dl.push_back(dataname_friction_coeff);
+     if (dataname_alpha.size() > 0) {
+       dl.push_back(dataname_alpha);
+       if (dataname_wt.size() > 0) dl.push_back(dataname_wt);
+     }
+ 
+     model::varnamelist vl(1, varname_u);
+ 
+     std::vector<std::string> aux_vars;
+     md.auxilliary_variables_of_Neumann_terms(varname_u, aux_vars);
+     for (size_type i = 0; i < aux_vars.size(); ++i) {
+       vl.push_back(aux_vars[i]);
+       tl.push_back(model::term_description(varname_u, aux_vars[i], false));
+     }
+ 
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+   }
+ 
+ 
+ 
+ 
+ #endif
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+   //=========================================================================
+   //
+   //  Fictitious domain contact condition (HPP) : generic Nitsche's method
+   //
+   //=========================================================================
+ 
+ 
+   struct Nitsche_fictitious_domain_contact_brick : public virtual_brick {
+ 
+     scalar_type theta;
+     bool contact_only;
++>>>>>>> upstream
+ 
+     virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
+                                         const model::varnamelist &vl,
+                                         const model::varnamelist &dl,
+                                         const model::mimlist &mims,
+                                         model::real_matlist &matl,
+                                         model::real_veclist &vecl,
+                                         model::real_veclist &,
++<<<<<<< HEAD
++                                        size_type region,
++                                        build_version version) const;
++
++    integral_large_sliding_contact_brick() {
++      set_flags("Integral large sliding contact brick",
++                false /* is linear*/, false /* is symmetric */,
++                false /* is coercive */, true /* is real */,
++                false /* is complex */);
++    }
++
++  };
++
++
++
++
++  void integral_large_sliding_contact_brick::asm_real_tangent_terms
++  (const model &md, size_type /* ib */, const model::varnamelist &vl,
++   const model::varnamelist &dl, const model::mimlist &/* mims */,
++   model::real_matlist &matl, model::real_veclist &vecl,
++   model::real_veclist &, size_type /* region */,
++   build_version version) const {
++
++    fem_precomp_pool fppool;
++    base_matrix G;
++    size_type N = md.mesh_fem_of_variable(vl[0]).linked_mesh().dim();
++    contact_frame cf(N);
++    build_contact_frame(md, cf);
++    
++    size_type Nvar = vl.size(), Nu = cf.Urhs.size(), Nl = cf.Lrhs.size();
++    GMM_ASSERT1(Nvar == Nu+Nl, "Wrong size of variable list for integral "
++		"large sliding contact brick");
++    GMM_ASSERT1(matl.size() == Nvar*Nvar, "Wrong size of terms for "
++		"integral large sliding contact brick");
++    
++    if (version & model::BUILD_MATRIX) {
++      for (size_type i = 0; i < Nvar; ++i)
++	for (size_type j = 0; j < Nvar; ++j) {
++	  gmm::clear(matl[i*Nvar+j]);
++	  if (i <  Nu && j <  Nu) cf.UU(i,j)       = &(matl[i*Nvar+j]);
++	  if (i >= Nu && j <  Nu) cf.LU(i-Nu,j)    = &(matl[i*Nvar+j]);
++	  if (i <  Nu && j >= Nu) cf.UL(i,j-Nu)    = &(matl[i*Nvar+j]);
++	  if (i >= Nu && j >= Nu) cf.LL(i-Nu,j-Nu) = &(matl[i*Nvar+j]);
++	}
++    }
++    if (version & model::BUILD_RHS) {
++      for (size_type i = 0; i < vl.size(); ++i) {
++	if (i < Nu) cf.Urhs[i] = &(vecl[i*Nvar]);
++	else cf.Lrhs[i-Nu] = &(vecl[i*Nvar]);
++      }
++    }
++    
++    // Data : r, [friction_coeff,]
++    GMM_ASSERT1(dl.size() == 2, "Wrong number of data for integral large "
++		"sliding contact brick");
++    
++    const model_real_plain_vector &vr = md.real_variable(dl[0]);
++    GMM_ASSERT1(gmm::vect_size(vr) == 1, "Parameter r should be a scalar");
++    
++    const model_real_plain_vector &f_coeff = md.real_variable(dl[1]);
++    GMM_ASSERT1(gmm::vect_size(f_coeff) == 1,
++		"Friction coefficient should be a scalar");
++    
++    contact_elements ce(cf);
++    ce.init();
++    
++    for (size_type bnum = 0; bnum < boundaries.size(); ++bnum) {
++      mesh_region rg(boundaries[bnum].region);
++      const mesh_fem &mfu=md.mesh_fem_of_variable(boundaries[bnum].varname);
++      const mesh_fem &mfl=md.mesh_fem_of_variable(boundaries[bnum].multname);
++      const mesh_im &mim = *(boundaries[bnum].mim);
++      const mesh &m = mfu.linked_mesh();
++      mfu.linked_mesh().intersect_with_mpi_region(rg);
++      
++      for (getfem::mr_visitor v(rg, m); !v.finished(); ++v) {
++	// cout << "boundary " << bnum << " element " << v.cv() << endl;
++	size_type cv = v.cv();
++	bgeot::pgeometric_trans pgt = m.trans_of_convex(cv);
++	pfem pf_s = mfu.fem_of_element(cv);
++	pfem pf_sl = mfl.fem_of_element(cv);
++	pintegration_method pim = mim.int_method_of_element(cv);
++	bgeot::vectors_to_base_matrix(G, m.points_of_convex(cv));
++	
++	pfem_precomp pfpu
++	  = fppool(pf_s,&(pim->approx_method()->integration_points()));
++	pfem_precomp pfpl
++	  = fppool(pf_sl,&(pim->approx_method()->integration_points()));
++	fem_interpolation_context ctxu(pgt,pfpu,size_type(-1), G, cv, v.f());
++	fem_interpolation_context ctxl(pgt,pfpl,size_type(-1), G, cv, v.f());
++	
++	for (size_type k = 0;
++	     k < pim->approx_method()->nb_points_on_face(v.f()); ++k) {
++	  size_type ind
++	    = pim->approx_method()->ind_first_point_on_face(v.f()) + k;
++	  ctxu.set_ii(ind);
++	  ctxl.set_ii(ind);
++	  if (!(ce.add_point_contribution
++	       (bnum, ctxu, ctxl,pim->approx_method()->coeff(ind),
++		f_coeff[0], vr[0], version))) return;
++	}
++      }
++    }
++  }
++  
++
++  // r ne peut pas �tre variable pour le moment.
++  // dataname_friction_coeff ne peut pas �tre variable non plus ...
++
++  size_type add_integral_large_sliding_contact_brick
++  (model &md, const mesh_im &mim, const std::string &varname_u,
++   const std::string &multname, const std::string &dataname_r,
++   const std::string &dataname_friction_coeff, size_type region) {
++
++    integral_large_sliding_contact_brick *pbr
++      = new integral_large_sliding_contact_brick();
++    
++    pbr->add_boundary(varname_u, multname, mim, region);
++
++    model::termlist tl;
++    tl.push_back(model::term_description(varname_u, varname_u, false));
++    tl.push_back(model::term_description(varname_u, multname,  false));
++    tl.push_back(model::term_description(multname,  varname_u, false));
++    tl.push_back(model::term_description(multname,  multname,  false));
 +
 +    model::varnamelist dl(1, dataname_r);
 +    dl.push_back(dataname_friction_coeff);
 +
 +    model::varnamelist vl(1, varname_u);
 +    vl.push_back(multname);
 +    
 +    return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
 +  }
 +
 +
 +  void add_boundary_to_large_sliding_contact_brick
 +  (model &md, size_type indbrick, const mesh_im &mim,
 +   const std::string &varname_u, const std::string &multname,
 +   size_type region) {
 +    dim_type N = md.mesh_fem_of_variable(varname_u).linked_mesh().dim();
 +    pbrick pbr = md.brick_pointer(indbrick);
 +    md.touch_brick(indbrick);
 +    integral_large_sliding_contact_brick *p
 +      = dynamic_cast<integral_large_sliding_contact_brick *>
 +      (const_cast<virtual_brick *>(pbr.get()));
 +    GMM_ASSERT1(p, "Wrong type of brick");
 +    p->add_boundary(varname_u, multname, mim, region);
 +    md.add_mim_to_brick(indbrick, mim);
 +
 +    contact_frame cf(N);
 +    p->build_contact_frame(md, cf);
 +
 +    model::varnamelist vl;
 +    size_type nvaru = 0;
 +    for (size_type i = 0; i < cf.contact_boundaries.size(); ++i)
 +      if (cf.contact_boundaries[i].ind_U >= nvaru)
 +	{ vl.push_back(p->boundaries[i].varname); ++nvaru; }
 +
 +    size_type nvarl = 0;
 +    for (size_type i = 0; i < cf.contact_boundaries.size(); ++i)
 +      if (cf.contact_boundaries[i].ind_lambda >= nvarl)
 +	{ vl.push_back(p->boundaries[i].multname); ++nvarl; }
 +    md.change_variables_of_brick(indbrick, vl);
 +
 +    model::termlist tl;
 +    for (size_type i = 0; i < vl.size(); ++i)
 +      for (size_type j = 0; j < vl.size(); ++j)
 +	tl.push_back(model::term_description(vl[i], vl[j], false));
 +
 +    md.change_terms_of_brick(indbrick, tl);
 +  }
 +
 +  void add_rigid_obstacle_to_large_sliding_contact_brick
 +  (model &md, size_type indbrick, const std::string &obs) { // The velocity field should be added to an (optional) parameter ... (and optionaly represented by a rigid motion only ... the velocity should be modifiable ...
 +    pbrick pbr = md.brick_pointer(indbrick);
 +    md.touch_brick(indbrick);
 +     integral_large_sliding_contact_brick *p
 +       = dynamic_cast<integral_large_sliding_contact_brick *>
 +       (const_cast<virtual_brick *>(pbr.get()));
 +    GMM_ASSERT1(p, "Wrong type of brick");
 +    p->add_obstacle(obs);
 +  }
 +
++=======
+                                         size_type /* region */,
+                                         build_version version) const {
+ 					  
+       // cout << "begining assembly" << endl;
+ 
+       // Integration method
+       GMM_ASSERT1(mims.size() == 1, "Nitsche fictitious domain contact "
+                   "bricks need a single mesh_im");
+       const mesh_im &mim = *mims[0];
+       const mesh &m = mim.linked_mesh();
+       size_type N = m.dim();
+ 
+       GMM_ASSERT1(vl.size() <= 2, "Auxilliary variable not taken into "
+                   "account for the moment");
+ 
+       GMM_ASSERT1(vl.size() >= 2, "Nitsche fictitious domain contact "
+                   "bricks need two variables");
+ 
+       const model_real_plain_vector &UU1 = md.real_variable(vl[0]);
+       const mesh_fem &mf_u1 = md.mesh_fem_of_variable(vl[0]);
+       const model_real_plain_vector &UU2 = md.real_variable(vl[1]);
+       const mesh_fem &mf_u2 = md.mesh_fem_of_variable(vl[1]);
+ 
+       model_real_plain_vector U1(mf_u1.nb_basic_dof()), U2(mf_u2.nb_basic_dof());
+       mf_u1.extend_vector(UU1, U1); mf_u2.extend_vector(UU2, U2);
+ 
+       GMM_ASSERT1(dl.size() > 2, "Nitsche fictitious domain contact "
+                   "bricks need at least 2 data");
+ 
+       const model_real_plain_vector &DD1 = md.real_variable(dl[0]);
+       const mesh_fem &mf_d1 = md.mesh_fem_of_variable(dl[0]);
+       const model_real_plain_vector &DD2 = md.real_variable(dl[1]);
+       const mesh_fem &mf_d2 = md.mesh_fem_of_variable(dl[1]);
+ 
+       model_real_plain_vector D1(mf_d1.nb_basic_dof()), D2(mf_d2.nb_basic_dof());
+       mf_d1.extend_vector(DD1, D1); mf_d2.extend_vector(DD2, D2);
+ 
+       const model_real_plain_vector &GAMMA0 = md.real_variable(dl[2]);
+       GMM_ASSERT1(GAMMA0.size() == 1, "Gamma0 should be a scalar parameter");
+       scalar_type gamma0 = GAMMA0[0];
+ 
+       scalar_type f_coeff(0), alpha(0);
+       const model_real_plain_vector *WWT1 = 0, *WWT2 = 0;
+       model_real_plain_vector WT1(mf_u1.nb_basic_dof()), WT2(mf_u2.nb_basic_dof());
+       if (dl.size() > 3) {
+         const model_real_plain_vector &FRICT = md.real_variable(dl[3]);
+         GMM_ASSERT1(FRICT.size() == 1, "The friction coefficient should "
+                     "be a scalar parameter");
+         f_coeff = FRICT[0];
+ 
+         if (dl.size() > 4) {
+           const model_real_plain_vector &ALPHA = md.real_variable(dl[4]);
+           GMM_ASSERT1(ALPHA.size() == 1, "Alpha should be a scalar parameter");
+           alpha = ALPHA[0];
+ 
+           if (dl.size() > 6) {
+             WWT1 = &(md.real_variable(dl[5]));
+             GMM_ASSERT1(&mf_u1 == &(md.mesh_fem_of_variable(dl[5])),
+                         "wt1 should be described on the same fem than u1");
+             WWT2 = &(md.real_variable(dl[6]));
+             GMM_ASSERT1(&mf_u2 == &(md.mesh_fem_of_variable(dl[6])),
+                         "wt2 should be described on the same fem than u2");
+             mf_u1.extend_vector(*WWT1, WT1); mf_u2.extend_vector(*WWT2, WT2);
+           }
+         }
+       }
+ 
+ 
+ 
+       GMM_ASSERT1(&(mf_u1.linked_mesh()) == &m && &(mf_u2.linked_mesh()) == &m
+                   && &(mf_d1.linked_mesh()) == &m
+                   && &(mf_d2.linked_mesh()) == &m,
+                   "All data and variables should be defined on the same mesh");
+ 
+       // cout << "Computing projection ..." << endl;
+ 
+       bgeot::rtree tree;
+ 
+ 
+ 	    
+ 	    
+       
+       for (dal::bv_visitor cv(mf_d2.convex_index()); !cv.finished(); ++cv) {
+ 	base_node min,max;
+ //      base_node min = m.points_of_convex(cv)[0], max = min;
+ //      for (size_type i = 1; i <  m.nb_points_of_convex(cv); // pourquoi ça?
+ //          ++i) {
+ //       cout << " cv = " << cv << ", min = " << min << ", max = " << max << endl;
+ //       for (size_type k = 0; k < N; ++k) {
+ //            const base_node &x = m.points_of_convex(cv)[k];
+ //           min[k] = std::min(min[k], x[k]);
+ //           max[k] = std::max(max[k], x[k]);
+ //         }
+ //       cout << " cv = " << cv << ", min = " << min << ", max = " << max << endl;
+ //               }
+ //    
+ //       for (size_type k = 0; k < N; ++k) {
+ //         min[k] -= (max[k] - min[k]) / 5.;
+ //         max[k] += (max[k] - min[k]) / 5.;
+ //          }
+        scalar_type EPS = 1E-13;
+        bounding_box(min, max, mf_d2.linked_mesh().points_of_convex(cv),
+                     mf_d2.linked_mesh().trans_of_convex(cv));
+        for (unsigned k=0; k < min.size(); ++k) { min[k]-=EPS; max[k]+=EPS; }
+ 
+  
+  
+  
+  
+  
+         tree.add_box(min, max, cv);
+ 
+ 
+       }
+ 
+       // cout << "Projection computed." << endl;
+ 
+       if (version & model::BUILD_MATRIX) {
+         gmm::clear(matl[0]);
+         gmm::clear(matl[1]);
+         gmm::clear(matl[2]);
+         gmm::clear(matl[3]);
+       }
+ 
+       if (version & model::BUILD_RHS) {
+         gmm::clear(vecl[0]);
+         gmm::clear(vecl[1]);
+         gmm::clear(vecl[2]);
+         gmm::clear(vecl[3]);
+       }
+ 
+       base_matrix G1, G2, GPr(N,N);
+       base_vector coeff, Velem, wt1(N), wt2(N), tv1n, tv2n;
+       base_matrix Melem, grad_d2(1, N), grad_d1(1, N), tv1, tv2;
+       base_small_vector d2(1), n1(N), n2(N), Pr(N), zeta(N), u1(N), u2(N);
+       base_tensor tG1, tGdu1, tGddu1, tbv1, tbv2;
+       scalar_type gap, u1n, u2n;
+       size_type cv2(-1),qdim1,qdim2;
+ 
+       bgeot::multi_index sizes_tGdu1(1), sizes_tGddu1(3);
+       sizes_tGdu1[0] = short_type(N);
+       tG1.adjust_sizes(sizes_tGdu1);
+       sizes_tGdu1.push_back(short_type(N));
+       sizes_tGddu1[2] = short_type(N);
+       
+       // cout << "begining gauss points loop" << endl;
+       
+       for (dal::bv_visitor cv(mim.convex_index()); !cv.finished(); ++cv) {
+ 
+         // cout << "element " << cv << endl;
+ 
+ 
+         pintegration_method pim = mim.int_method_of_element(cv);
+         if (pim->type() != IM_APPROX) continue; 
+ 
+ 
+         // cout << "pim = " << int(pim->type()) << endl;
+         // cout << "pim = " << pim->approx_method() << endl;
+ 
+         bgeot::vectors_to_base_matrix(G1, m.points_of_convex(cv));
+         
+         bgeot::pgeometric_trans pgt = m.trans_of_convex(cv);
+         pfem pf_u1 = mf_u1.fem_of_element(cv);
+         pfem pf_d1 = mf_d1.fem_of_element(cv);
+         size_type nbdof1 = mf_u1.nb_basic_dof_of_element(cv);
+         sizes_tGddu1[0] = sizes_tGddu1[1] = sizes_tGdu1[0]= short_type(nbdof1);
+         tGdu1.adjust_sizes(sizes_tGdu1);
+         tGddu1.adjust_sizes(sizes_tGddu1);
+  	
+ 	
+ 	
+         scalar_type gamma(0); 
+         size_type nbpt = pim->approx_method()->nb_points();
+         for (size_type ipt = 0; ipt < nbpt; ++ipt) {
+           
+           const base_node xref = pim->approx_method()->integration_points()[ipt];
+           
+           fem_interpolation_context ctx_u1(pgt, pf_u1, xref, G1, cv);
+           base_node x0 = ctx_u1.xreal();
+ 
+ 
+ 	  
+           scalar_type weight = pim->approx_method()->coeff(ipt) * ctx_u1.J();
+        	  
+           // computation of h for gamma = gamma0*h
+ 
+           if (ipt == 0) {
+             scalar_type emax, emin;
+             gmm::condition_number(ctx_u1.K(),emax,emin);
+             gamma = gamma0 * emax * sqrt(scalar_type(N));
+           }
+ 	  
+           // computation of u1, w1, f_friction
+           slice_vector_on_basic_dof_of_element(mf_u1, U1, cv, coeff);
+           ctx_u1.pf()->interpolation(ctx_u1, coeff, u1, bgeot::dim_type(N));
+           if (WWT1) {
+             slice_vector_on_basic_dof_of_element(mf_u1, WT1, cv, coeff);
+             ctx_u1.pf()->interpolation(ctx_u1, coeff, wt1, bgeot::dim_type(N));
+           }
+ 		  
+ 
+           // Computation of n1
+           fem_interpolation_context ctx_d1(pgt, pf_d1, xref, G1, cv);
+           slice_vector_on_basic_dof_of_element(mf_d1, D1, cv, coeff);
+           ctx_d1.pf()->interpolation_grad(ctx_d1, coeff, grad_d1, 1);
+           gmm::copy(grad_d1.as_vector(), n1);
+           gmm::scale(n1, 1./gmm::vect_norm2(n1));
+ 	  
+ 
+           // cout << " Element " << cv << " point " << ipt << " elt ref : " <<
+           // pim->approx_method()->integration_points()[ipt] << " elt reel : " << x0 << endl; // Attention cv+1 pour matlab
+ 
+ 	    
+            //Definition de la projection et computation of n2
+ 
+           pfem pf_d2 = mf_d2.fem_of_element(cv);
+ 
+           fem_interpolation_context ctx_d2(pgt, pf_d2, xref, G1, cv);
+ 
+           slice_vector_on_basic_dof_of_element(mf_d2, D2, cv, coeff);
+ 
+           ctx_d2.pf()->interpolation(ctx_d2, coeff, d2, 1);
+ 
+           ctx_d2.pf()->interpolation_grad(ctx_d2, coeff, grad_d2, 1);
+           gmm::copy(grad_d2.as_vector(), n2);
+           gmm::scale(n2, 1./gmm::vect_norm2(n2));
+ 
+  
+           base_node y0 = x0, yref(N);
+           gmm::add(gmm::scaled(gmm::mat_row(grad_d2, 0),
+                    -d2[0] / gmm::vect_norm2_sqr(gmm::mat_row(grad_d2, 0))),
+                    y0);
+ 	     
+ 	  
+           bgeot::rtree::pbox_set pbs;
+ 	  
+           tree.find_boxes_at_point(y0, pbs);
+ 	   
+           bgeot::rtree::pbox_set::const_iterator it = pbs.begin();
+ 	  
+ 	  
+           bool found = false;
+           size_type nbdof2(0);
+           
+ 	  for (; it != pbs.end(); ++it) {
+ 	    cv2 = (*it)->id;
+             bgeot::pgeometric_trans pgty =  m.trans_of_convex(cv2);
+             nbdof2 = mf_u2.nb_basic_dof_of_element(cv2);
+             bgeot::vectors_to_base_matrix(G2, m.points_of_convex(cv2));
+ 
+             bgeot::geotrans_inv_convex gic;
+             gic.init(m.points_of_convex(cv2), pgty);
+ 
+             gic.invert(y0, yref);
+             if (pgty->convex_ref()->is_in(yref) < 1E-10)
+               { found = true; break; }
+           }
+ 
+           GMM_ASSERT1(found && (cv2 != size_type(-1)),
+                       "Projection not found ...");
+ 
+         //  cout << "Found element : " << cv2 << " yref = " << yref << "y0 = " << y0 << endl; // Attention cv2+1 pour matlab
+      
+ 	  
+ 	  
+ 	  // Computation of gap
+ 	  gap = 0;
+           for( size_type i=0; i<N; ++i)
+             gap += (x0[i]-y0[i])*n2[i];	  	  
+ 	  
+           pfem pf_u2 = mf_u2.fem_of_element(cv2);
+           fem_interpolation_context ctx_u2(pgt, pf_u2, yref, G2, cv2);
+ 
+           // computation of u2
+           slice_vector_on_basic_dof_of_element(mf_u2, U2, cv2, coeff);
+           ctx_u2.pf()->interpolation(ctx_u2, coeff, u2, bgeot::dim_type(N));
+           if (WWT2) {
+             slice_vector_on_basic_dof_of_element(mf_u2, WT2, cv2, coeff);
+             ctx_u2.pf()->interpolation(ctx_u2, coeff, wt2, bgeot::dim_type(N));
+           }
+ 
+           u1n = gmm::vect_sp(u1, n2); u2n = gmm::vect_sp(u2, n2);
+           
+           md.compute_Neumann_terms(1, vl[0], mf_u1, U1, ctx_u1, n1, tG1);
+           md.compute_Neumann_terms(2, vl[0], mf_u1, U1, ctx_u1, n1, tGdu1);
+           md.compute_Neumann_terms(3, vl[0], mf_u1, U1, ctx_u1, n1, tGddu1);
+           // gmm::clear(tG1.as_vector()); gmm::clear(tGdu1.as_vector()); gmm::clear(tGddu1.as_vector()); // A supprimer
+ 
+           ctx_u1.pf()->real_base_value(ctx_u1, tbv1);
+           ctx_u2.pf()->real_base_value(ctx_u2, tbv2);
+ 
+ 	  
+ 
+ 	  qdim1=  ctx_u1.pf()->target_dim();
+ 	  qdim2=  ctx_u2.pf()->target_dim();
+ 	  
+ 	  
+ 	  vectorize_base_tensor(tbv1, tv1, nbdof1, qdim1, N);
+ 	  vectorize_base_tensor(tbv2, tv2, nbdof2, qdim2, N);
+ 	  
+ 	  
+ 	  	  
+ 
+           for(size_type i=0; i<N; ++i)
+             zeta[i] = tG1[i] +
+               ( (gap - (alpha-1.)*u1n+(alpha-1.)*u2n)*n2[i]
+                 + alpha*(wt1[i]-wt2[i]) + alpha*u1[i] - alpha*u2[i]) / gamma;	  
+ 
+ 
+           coupled_projection(zeta, n2, f_coeff, Pr);
+ 	  coupled_projection_grad(zeta, n2, f_coeff, GPr);
+ 
+           gmm::resize(tv1n, nbdof1); gmm::clear(tv1n);
+           gmm::resize(tv2n, nbdof2); gmm::clear(tv2n);
+ 	  for (size_type k = 0; k < nbdof1; ++k)
+ 	    for (size_type l = 0; l < N; ++l)
+ 	       tv1n[k] += n2[l] * tv1(k,l);
+ 	  for (size_type k = 0; k < nbdof2; ++k)
+ 	    for (size_type l = 0; l < N; ++l)
+               tv2n[k] += n2[l] * tv2(k,l);
+ 
+ 
+ 
+           // Matrice tangente 
+           if (version & model::BUILD_MATRIX){         
+ 	    // Matrice en u1,u1
+             gmm::resize(Melem, nbdof1, nbdof1); gmm::clear(Melem);
+             for (size_type j = 0; j < nbdof1; ++j)
+               for (size_type k = 0; k < nbdof1; ++k){
+ 		scalar_type res(0);
+                 for (size_type i = 0; i < N; ++i) {
+                   if (theta != scalar_type(0)) { 
+                     res -= theta*gamma*tGdu1(k, i) * tGdu1(j, i); // l'inverse était écrit
+                     res += theta*gamma*(Pr[i]-tG1[i])*(tGddu1(j,k,i));
+                     for (size_type l =0; l<N; ++l){
+                       res += theta*GPr(i,l)*(gamma*tGdu1(k,l)
+                                              +alpha*tv1(k,l)+(scalar_type(1)-alpha)*n2[l]*tv1n[k])*tGdu1(j,i);
+ 		    }
+                   }
+ 		  for (size_type l =0; l<N;++l)
+                     res += GPr(i,l)*(-tGdu1(k,l)-(alpha*tv1(k,l)+(scalar_type(1)-alpha)*n2[l]*tv1n[k])/(gamma))*tv1(j,i); // bien n2 ou n1 ici   
+                 }
+                 Melem(j, k)=res;
+ 	      }
+             gmm::scale(Melem,weight);
+ 	    // cout << "Melem final 1" << Melem << endl;
+             mat_elem_assembly(matl[0], Melem, mf_u1, cv, mf_u1, cv);
+ 
+ 	    
+             // Matrice en u1,u2
+             gmm::resize(Melem, nbdof1, nbdof2); gmm::clear(Melem);
+             for (size_type j = 0; j < nbdof2; ++j)
+               for (size_type k = 0; k < nbdof1; ++k){
+ 		scalar_type res(0);
+                 for (size_type i = 0; i < N; ++i) {
+                   if (theta != scalar_type(0)) {
+                     for (size_type l =0; l<N;++l)
+                       res -= theta*GPr(i,l)*(alpha*tv2(j,l)+(scalar_type(1)-alpha)*n2[l]*tv2n[j])*tGdu1(k,i);
+ 						}
+ 		  for (size_type l =0; l<N;++l)
+                     res += GPr(i,l)*(alpha*tv2(j,l)+(scalar_type(1)-alpha)*n2[l]*tv2n[j])*tv1(k,i)/(gamma);				
+                 } 
+ 		Melem(k, j)=res;				   
+ 	      }
+             gmm::scale(Melem,weight);
+             // cout << "Melem final 2" << Melem << endl;
+             mat_elem_assembly(matl[1], Melem, mf_u1, cv, mf_u2, cv2);	
+ 	    
+ 	    
+             // Matrice en fonction de u2,u1
+             gmm::resize(Melem, nbdof2, nbdof1); gmm::clear(Melem);
+             for (size_type j = 0; j < nbdof1; ++j)
+               for (size_type k = 0; k < nbdof2; ++k){
+ 		scalar_type res(0);
+                 for (size_type i = 0; i < N; ++i) 
+ 		  for (size_type l = 0; l < N; ++l)
+                     res += GPr(i,l)*(tGdu1(j,l)-(-alpha*tv1(j,l)-(scalar_type(1)-alpha)*n2[l]*tv1n[j])/(gamma))*tv2(k,i);
+ 		Melem(k, j)=res;
+ 	      }
+             gmm::scale(Melem,weight);
+             // cout << "Melem final 3" << Melem << endl;
+             mat_elem_assembly(matl[2], Melem, mf_u2, cv2, mf_u1, cv);    
+ 	    
+ 	    
+ 	    // Matrice en u2,u2
+             gmm::resize(Melem, nbdof2, nbdof2); gmm::clear(Melem);
+             for (size_type j = 0; j < nbdof2; ++j)
+               for (size_type k = 0; k < nbdof2; ++k){
+ 		scalar_type res(0);
+                 for (size_type i = 0; i < N; ++i) {
+                   for (size_type l =0; l<N;++l)
+                     res -= GPr(i,l)*(alpha*tv2(k,l)+(scalar_type(1)-alpha)*n2[l]*tv2n[k])*tv2(j,i)/(gamma);			
+                 } 
+ 		Melem(j, k)=res;				   
+ 	      }
+             gmm::scale(Melem,weight);
+             // cout << "Melem final 4" << Melem << endl;
+             mat_elem_assembly(matl[3], Melem, mf_u2, cv2, mf_u2, cv2);	
+           }
+ 				           
+ 				           
+           // Matrice du second Membre		             
+           if (version & model::BUILD_RHS){
+ 	    // Second membre en u1
+ 	    gmm::resize(Velem, nbdof1); gmm::clear(Velem);
+             for (size_type j = 0; j < nbdof1; ++j){
+ 	      scalar_type res(0);
+               for (size_type i = 0; i < N; ++i){
+                 if (theta != scalar_type(0)){
+                   res += theta*gamma*tG1[i] * tGdu1(j, i); 
+                   res -= theta*gamma*Pr[i] * tGdu1(j, i);
+                 }
+                 res +=Pr[i]*tv1(j,i);
+               }
+               Velem[j]=res;
+ 	    }
+             gmm::scale(Velem, weight);
+ 	    // cout << "Velem final 1" << Velem << endl;
+             vec_elem_assembly(vecl[0], Velem, mf_u1, cv);
+ 	    
+ 
+ 	    // Second membre en u2	    
+             gmm::resize(Velem, nbdof2);gmm::clear(Velem);
+             for (size_type j = 0; j < nbdof2; ++j){
+ 	      scalar_type res(0);
+               for (size_type i = 0; i < N; ++i)
+                 res -= Pr[i]*tv2(j,i);
+ 	      Velem[j]=res;
+ 	    }	        
+ 	    gmm::scale(Velem, weight);
+ 	    // cout << "Velem final 2" << Velem << endl;
+             vec_elem_assembly(vecl[3], Velem, mf_u2, cv2);
+           }
+ 
+ 
+ //           size_type nit = 0;
+ //           while (gmm::abs(d0) > 1E-10 && ++nit < 1000) {
+ //             for (size_type k = 0; k < N; ++k) {
+ //               pt_eval[k] += EPS;
+ //               d1 = scalar_type(obstacles_parsers[irigid_obstacle].Eval());
+ //               n[k] = (d1 - d0) / EPS;
+ //               pt_eval[k] -= EPS;
+ //             }
+ 
+ //             gmm::add(gmm::scaled(n, -d0 / gmm::vect_norm2_sqr(n)), pt_eval);
+ //             // A simple line search could be added
+ //             d0 = scalar_type(obstacles_parsers[irigid_obstacle].Eval());
+ //           }
+ //           GMM_ASSERT1(nit < 1000, "Projection on rigid obstacle did not converge");
+ 
+ //           ct.master_point.resize(N);
+ //           gmm::copy(pt_eval, ct.master_point);
+ 
+ 
+ 
+ 
+ 
+ 
+         }
+ 
+       }
+ 
+ 
+       // cout << "end assembly" << endl;
+ 
+     }
+     
+     Nitsche_fictitious_domain_contact_brick(scalar_type theta_,
+                                             bool nofriction) {
+       theta = theta_;
+       contact_only = nofriction;
+       set_flags("Integral Nitsche contact and friction with rigid "
+                 "obstacle brick",
+                 false /* is linear*/, false /* is symmetric */,
+                 false /* is coercive */, true /* is real */,
+                 false /* is complex */, false /* compute each time */,
+                 false /* has a Neumann term */);
+     }
+ 
+   };
+ 
+ 
+ 
+   size_type add_Nitsche_fictitious_domain_contact_brick
+   (model &md, const mesh_im &mim, const std::string &varname_u1,
+    const std::string &varname_u2, const std::string &dataname_d1,
+    const std::string &dataname_d2, const std::string &dataname_gamma0,
+    scalar_type theta,
+    const std::string &dataname_friction_coeff,
+    const std::string &dataname_alpha,
+    const std::string &dataname_wt1, const std::string &dataname_wt2) {
+ 
+     bool nofriction = (dataname_friction_coeff.size() == 0);
+     pbrick pbr = new Nitsche_fictitious_domain_contact_brick(theta,nofriction);
+ 
+     model::termlist tl;
+     tl.push_back(model::term_description(varname_u1, varname_u1, false));
+     tl.push_back(model::term_description(varname_u1, varname_u2, false));
+     tl.push_back(model::term_description(varname_u2, varname_u1, false));
+     tl.push_back(model::term_description(varname_u2, varname_u2, false));
+ 
+ 
+     model::varnamelist dl(1, dataname_d1);
+     dl.push_back(dataname_d2);
+     dl.push_back(dataname_gamma0);
+     if (!nofriction) dl.push_back(dataname_friction_coeff);
+     if (dataname_alpha.size() > 0) {
+       dl.push_back(dataname_alpha);
+       if (dataname_wt1.size() > 0)
+         { dl.push_back(dataname_wt1); dl.push_back(dataname_wt2); }
+     }
+ 
+     model::varnamelist vl(1, varname_u1);
+     vl.push_back(varname_u2);
+ 
+     std::vector<std::string> aux_vars;
+     md.auxilliary_variables_of_Neumann_terms(varname_u1, aux_vars);
+     for (size_type i = 0; i < aux_vars.size(); ++i) {
+       vl.push_back(aux_vars[i]);
+       tl.push_back(model::term_description(varname_u1, aux_vars[i], false));
+     }
+ //     aux_vars.resize(0);
+ //     md.auxilliary_variables_of_Neumann_terms(varname_u2, aux_vars);
+ //     for (size_type i = 0; i < aux_vars.size(); ++i) {
+ //       vl.push_back(aux_vars[i]);
+ //       tl.push_back(model::term_description(varname_u2, aux_vars[i], false));
+ //     }
+ 
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim),
+                         size_type(-1));
+   }
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
++>>>>>>> upstream
  }  /* end of namespace getfem.                                             */
diff --cc src/getfem_contact_and_friction_nodal.cc
index 8aebc3a,b3241f0..e64c9bb
--- a/src/getfem_contact_and_friction_nodal.cc
+++ b/src/getfem_contact_and_friction_nodal.cc
@@@ -24,16 -24,7 +24,20 @@@
  #include "getfem/getfem_contact_and_friction_common.h"
  #include "getfem/getfem_assembling.h"
  
++<<<<<<< HEAD:src/getfem_contact_and_friction_nodal.cc
 +#include <getfem/getfem_arch_config.h>
 +#if GETFEM_HAVE_MUPARSER_MUPARSER_H
 +#include <muParser/muParser.h>
 +#elif GETFEM_HAVE_MUPARSER_H
 +#include <muParser.h>
 +#endif
 +
 +#ifdef GETFEM_HAVE_QHULL_QHULL_H
 +#include <getfem/getfem_mesher.h>
 +#else
++=======
+ #ifndef GETFEM_HAVE_QHULL_QHULL_H
++>>>>>>> upstream:src/getfem_contact_and_friction_nodal.cc
  #include <getfem/bgeot_kdtree.h>
  #endif
  
@@@ -756,6 -743,6 +760,7 @@@ namespace getfem 
              if (two_variables) {
                gmm::mult(gmm::transposed(gmm::scaled(BBN2,-r)), T_n_u2, tmp1);
                gmm::add(tmp1, T_u2_u2);
++<<<<<<< HEAD:src/getfem_contact_and_friction_nodal.cc
              }
  
              if (!contact_only) {
@@@ -766,6 -753,6 +771,18 @@@
                  gmm::add(tmp1, T_u2_u2);
                }
              }
++=======
++            }
++
++            if (!contact_only) {
++              gmm::mult(gmm::transposed(gmm::scaled(BBT1,-r)), T_t_u1, tmp1);
++              gmm::add(tmp1, T_u1_u1);
++              if (two_variables) {
++                gmm::mult(gmm::transposed(gmm::scaled(BBT2,-r)), T_t_u2, tmp1);
++                gmm::add(tmp1, T_u2_u2);
++              }
++            }
++>>>>>>> upstream:src/getfem_contact_and_friction_nodal.cc
  	  }
  
  	  if (!contact_only && !Tresca_version) {
@@@ -1096,9 -1083,8 +1113,14 @@@
        size_type nbvar = 2 + (contact_only ? 0 : 1) + (two_variables ? 1 : 0);
        GMM_ASSERT1(vl.size() == nbvar,
                    "Wrong number of variables for contact brick");
++<<<<<<< HEAD:src/getfem_contact_and_friction_nodal.cc
 +           size_type nbdl = 3 + (contact_only ? 0 : 1) + (Tresca_version ? 1 : 0)
 +        + (friction_dynamic_term ? 1 : 0);
 +     
++=======
+       size_type nbdl = 3 + (contact_only ? 0 : 1) + (Tresca_version ? 1 : 0)
+         + (friction_dynamic_term ? 2 : 0);
++>>>>>>> upstream:src/getfem_contact_and_friction_nodal.cc
        GMM_ASSERT1(dl.size() == nbdl, "Wrong number of data for contact brick, "
                    << dl.size() << " should be " << nbdl);
  
@@@ -1180,7 -1166,13 +1202,17 @@@
      Coulomb_friction_brick(int aug_version, bool contact_only_,
                             bool two_variables_=false,
                             bool Tresca_version_=false,
++<<<<<<< HEAD:src/getfem_contact_and_friction_nodal.cc
 +                           bool Hughes_stabilized_=false) {
++=======
+                            bool Hughes_stabilized_=false,
+                            bool friction_dynamic_term_=false) {
+ 
+ #if GETFEM_PARA_LEVEL > 1
+     if (!getfem::MPI_IS_MASTER()) GMM_WARNING1("Nodal contact bricks don't support GETFEM_PARA_LEVEL > 1 yet!!!");
+ #endif
+ 
++>>>>>>> upstream:src/getfem_contact_and_friction_nodal.cc
        if (aug_version == 4 && contact_only_) aug_version = 3;
        augmentation_version = aug_version;
        GMM_ASSERT1(aug_version >= 1 && aug_version <= 4,
@@@ -1288,8 -1280,9 +1320,14 @@@
     const std::string &dataname_r, CONTACT_B_MATRIX &BN,
     std::string dataname_gap, std::string dataname_alpha,
     int aug_version, bool Hughes_stabilized) {
++<<<<<<< HEAD:src/getfem_contact_and_friction_nodal.cc
 +    Coulomb_friction_brick *pbr_
 +      = new Coulomb_friction_brick(aug_version, true, false,false, Hughes_stabilized);
++=======
+ 
+     Coulomb_friction_brick *pbr_
+       = new Coulomb_friction_brick(aug_version, true, false, false, Hughes_stabilized);
++>>>>>>> upstream:src/getfem_contact_and_friction_nodal.cc
      pbr_->set_BN1(BN);
      pbrick pbr = pbr_;
  
@@@ -1331,10 -1324,14 +1369,21 @@@
     CONTACT_B_MATRIX &BN, CONTACT_B_MATRIX &BT,
     std::string dataname_friction_coeff,
     std::string dataname_gap, std::string dataname_alpha,
++<<<<<<< HEAD:src/getfem_contact_and_friction_nodal.cc
 +   int aug_version, bool Tresca_version, std::string dataname_threshold, bool Hughes_stabilized) {
 +    Coulomb_friction_brick *pbr_
 +      = new Coulomb_friction_brick(aug_version,false, false,
 +                                   Tresca_version, Hughes_stabilized);
++=======
+    int aug_version, bool Tresca_version, const std::string dataname_threshold,
+    std::string dataname_gamma, std::string dataname_wt, bool Hughes_stabilized) {
+ 
+     bool dynamic_terms = (dataname_gamma.size() > 0);
+ 
+     Coulomb_friction_brick *pbr_
+       = new Coulomb_friction_brick(aug_version,false, false,
+                             Tresca_version, Hughes_stabilized, dynamic_terms);
++>>>>>>> upstream:src/getfem_contact_and_friction_nodal.cc
      pbr_->set_BN1(BN);
      pbr_->set_BT1(BT);
      pbrick pbr = pbr_;
@@@ -1364,6 -1361,10 +1413,13 @@@
      }
      dl.push_back(dataname_alpha);
      dl.push_back(dataname_friction_coeff);
++<<<<<<< HEAD:src/getfem_contact_and_friction_nodal.cc
++=======
+     if (dataname_gamma.size()) {
+       dl.push_back(dataname_gamma);
+       dl.push_back(dataname_wt);
+     }
++>>>>>>> upstream:src/getfem_contact_and_friction_nodal.cc
      if (Tresca_version)
        dl.push_back(dataname_threshold);
  
diff --cc src/getfem_import.cc
index b66e65e,891f488..4601b04
--- a/src/getfem_import.cc
+++ b/src/getfem_import.cc
@@@ -136,8 -136,8 +136,13 @@@ namespace getfem 
       structure: $Nodes list_of_nodes $EndNodes $Elements list_of_elt
       $EndElements
    */
++<<<<<<< HEAD
 +  static void import_gmsh_msh_file(std::ifstream& f, mesh& m, int deprecate=0,
 +                            std::map<std::string, size_type> *region_map=NULL)
++=======
+   static void import_gmsh_mesh_file(std::ifstream& f, mesh& m, int deprecate=0,
+                                     std::map<std::string, size_type> *region_map=NULL)
++>>>>>>> upstream
    {
      gmm::stream_standard_locale sl(f);
      /* print general warning */
@@@ -717,7 -845,7 +850,11 @@@
  
    void import_mesh_gmsh(std::ifstream& f, mesh &m, 
                    std::map<std::string, size_type> &region_map) {
++<<<<<<< HEAD
 +    import_gmsh_msh_file(f,m, 0, &region_map);
++=======
+     import_gmsh_mesh_file(f,m, 0, &region_map);
++>>>>>>> upstream
    }
  
    void import_mesh_gmsh(const std::string& filename,
diff --cc src/getfem_interpolation.cc
index 132df23,059d800..2ad7ba2
--- a/src/getfem_interpolation.cc
+++ b/src/getfem_interpolation.cc
@@@ -43,15 -61,23 +61,32 @@@ namespace getfem 
      scalar_type mult = scalar_type(1);
  
      do {
++<<<<<<< HEAD
 +      for (dal::bv_visitor j(msh.convex_index()); !j.finished(); ++j) {
++=======
+       for (dal::bv_visitor j(rg_source.index()); !j.finished(); ++j) {
++>>>>>>> upstream
          if (mult > scalar_type(1) && !(cv_on_bound.is_in(j))) continue;
          bgeot::pgeometric_trans pgt = msh.trans_of_convex(j);
          bounding_box(min, max, msh.points_of_convex(j), pgt);
          for (size_type k=0; k < min.size(); ++k) { min[k]-=EPS; max[k]+=EPS; }
          if (extrapolation == 2) {
            if (mult == scalar_type(1))
++<<<<<<< HEAD
 +            for (short_type f = 0; f < msh.nb_faces_of_convex(j); ++f)
 +              if (!(msh.is_convex_having_neighbour(j, f))) cv_on_bound.add(j);
++=======
+             for (short_type f = 0; f < msh.nb_faces_of_convex(j); ++f) {
+               size_type neighbour_cv = msh.neighbour_of_convex(j, f);
+               if (!all_convexes && neighbour_cv != size_type(-1)) {
+                 // check if the neighbour is also contained in rg_source ...
+                 if (!rg_source.is_in(neighbour_cv)) 
+                   cv_on_bound.add(j); // ... if not, treat the element as a boundary one
+               }
+               else // boundary element of the overall mesh
+                 cv_on_bound.add(j);
+             }
++>>>>>>> upstream
            if (cv_on_bound.is_in(j)) {
              scalar_type h = scalar_type(0);
              for (size_type k=0; k < min.size(); ++k)
@@@ -83,7 -109,7 +118,11 @@@
  //               }
                ref_coords[ind] = pt_ref;
                dist[ind] = isin; cvx_pts[ind] = j;
++<<<<<<< HEAD
 +              pts_cvx[j][ind] = void_type();
++=======
+               pts_cvx[j].insert(ind);
++>>>>>>> upstream
                npt.sup(ind);
              }
            }
diff --cc src/getfem_mat_elem.cc
index 0a475b9,dfa28d8..32ff1d3
--- a/src/getfem_mat_elem.cc
+++ b/src/getfem_mat_elem.cc
@@@ -1,9 -1,9 +1,17 @@@
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2000-2012 Yves Renard
 + 
 + This file is a part of GETFEM++
 + 
++=======
+ 
+  Copyright (C) 2000-2012 Yves Renard
+ 
+  This file is a part of GETFEM++
+ 
++>>>>>>> upstream
   Getfem++  is  free software;  you  can  redistribute  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
@@@ -16,7 -16,7 +24,11 @@@
   You  should  have received a copy of the GNU Lesser General Public License
   along  with  this program;  if not, write to the Free Software Foundation,
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  
@@@ -514,67 -530,69 +542,93 @@@ namespace getfem 
        bool flag = false;
  
        if (!computed_on_real_element) {
- 	pre_tensors_for_linear_trans(ir == 0);
- 	const base_matrix& B = ctx.B(); // compute B and J
- 	scalar_type J=ctx.J();
- 	if (ir > 0) {
- 	  gmm::mult(B, un, up);
- 	  scalar_type nup = gmm::vect_norm2(up);
- 	  J *= nup; up /= nup;
- 	}
-      
- 	t = mref[ir]; gmm::scale(t.as_vector(), J);
- 	
- 	if (grad_reduction.size() > 0) {
- 	  std::deque<short_type>::const_iterator it = grad_reduction.begin(),
- 	    ite = grad_reduction.end();
- 	  for ( ; it != ite; ++it) {
- 	    (flag ? t:taux).mat_transp_reduction(flag ? taux:t, B, *it);
- 	    flag = !flag;
- 	  }
- 	}
- 	
- 	if (K_reduction.size() > 0) {
- 	  std::deque<short_type>::const_iterator it = K_reduction.begin(),
- 	    ite = K_reduction.end();
- 	  for ( ; it != ite; ++it) {
- 	    (flag ? t:taux).mat_transp_reduction(flag ? taux:t, ctx.K(), *it);
- 	    // (flag ? t:taux).mat_transp_reduction(flag ? taux:t, B, *it);
- 	    flag = !flag;
- 	  }
- 	}
+         pre_tensors_for_linear_trans(ir == 0);
+         const base_matrix& B = ctx.B(); // compute B and J
+         scalar_type J=ctx.J();
+         if (ir > 0) {
+           gmm::mult(B, un, up);
+           scalar_type nup = gmm::vect_norm2(up);
+ 	  J *= nup; //up /= nup;
+ 	  gmm::scale(up,1.0/nup);
+         }
+ 
+         t = mref[ir]; gmm::scale(t.as_vector(), J);
+ 
+         if (grad_reduction.size() > 0) {
+           std::deque<short_type>::const_iterator it = grad_reduction.begin(),
+             ite = grad_reduction.end();
+           for ( ; it != ite; ++it) {
+             (flag ? t:taux).mat_transp_reduction(flag ? taux:t, B, *it);
+             flag = !flag;
+           }
+         }
+ 
+         if (K_reduction.size() > 0) {
+           std::deque<short_type>::const_iterator it = K_reduction.begin(),
+             ite = K_reduction.end();
+           for ( ; it != ite; ++it) {
+             (flag ? t:taux).mat_transp_reduction(flag ? taux:t, ctx.K(), *it);
+             // (flag ? t:taux).mat_transp_reduction(flag ? taux:t, B, *it);
+             flag = !flag;
+           }
+         }
+ 
+         if (hess_reduction.size() > 0) {
+           std::deque<short_type>::const_iterator it = hess_reduction.begin(),
+             ite = hess_reduction.end();
+           for (short_type l = 1; it != ite; ++it, l = short_type(l*2)) {
+             (flag ? t:taux).mat_transp_reduction(flag ? taux:t, ctx.B3(), *it);
+             flag = !flag;
+           }
+         }
  
- 	if (hess_reduction.size() > 0) {
- 	  std::deque<short_type>::const_iterator it = hess_reduction.begin(),
- 	    ite = hess_reduction.end();
- 	  for (short_type l = 1; it != ite; ++it, l = short_type(l*2)) {
- 	    (flag ? t:taux).mat_transp_reduction(flag ? taux:t, ctx.B3(), *it);
- 	    flag = !flag;
- 	  }
- 	}
- 	
        } else { // non linear transformation and methods defined on real elements
++<<<<<<< HEAD
 +	bool first = true;
 +
 +	for (size_type ip=(ir == 0) ? 0 : pai->repart()[ir-1];
 +	     ip < pai->repart()[ir]; ++ip, first = false) {
 +	  ctx.set_ii(ip);
 +	  const base_matrix& B = ctx.B(); // J computed as side-effect
 +	  scalar_type J = ctx.J();
 +	  if (ir > 0) {
 +	    gmm::mult(B, un, up);
 +	    scalar_type nup = gmm::vect_norm2(up);
 +	    J *= nup; up /= nup;
 +	  }	  
 +	  add_elem(t, ctx, J, first, true, icb, sizes);
 +	}
 +
 +	// GMM_ASSERT1(!first, "No integration point on this element.");
 +	if (first) {
 +	  GMM_WARNING3("No integration point on this element. "
 +		       "Caution, returning a null tensor");
 +	  t.adjust_sizes(sizes); gmm::clear(t.as_vector());
 +	}
++=======
+         bgeot::multi_index sizes = pme->sizes(elt);
+ 
+         bool first = true;
+         for (size_type ip=(ir == 0) ? 0 : pai->repart()[ir-1];
+              ip < pai->repart()[ir]; ++ip, first = false) {
+           ctx.set_ii(ip);
+           const base_matrix& B = ctx.B(); // J computed as side-effect
+           scalar_type J = ctx.J();
+           if (ir > 0) {
+             gmm::mult(B, un, up);
+             scalar_type nup = gmm::vect_norm2(up);
+ 	    J *= nup; /*up /= nup;*/gmm::scale(up,1.0/nup);
+           }
+           add_elem(t, ctx, J, first, true, icb, sizes);
+         }
+ 
+         // GMM_ASSERT1(!first, "No integration point on this element.");
+         if (first) {
+           GMM_WARNING3("No integration point on this element. "
+                        "Caution, returning a null tensor");
+           t.adjust_sizes(sizes); gmm::clear(t.as_vector());
+         }
++>>>>>>> upstream
        }
  
        /* Applying linear transformation for non tau-equivalent elements.   */
diff --cc src/getfem_mat_elem_type.cc
index 38bbf13,b111f87..275be67
--- a/src/getfem_mat_elem_type.cc
+++ b/src/getfem_mat_elem_type.cc
@@@ -1,9 -1,9 +1,17 @@@
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2000-2012 Yves Renard
 + 
 + This file is a part of GETFEM++
 + 
++=======
+ 
+  Copyright (C) 2000-2012 Yves Renard
+ 
+  This file is a part of GETFEM++
+ 
++>>>>>>> upstream
   Getfem++  is  free software;  you  can  redistribute  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
@@@ -16,7 -16,7 +24,11 @@@
   You  should  have received a copy of the GNU Lesser General Public License
   along  with  this program;  if not, write to the Free Software Foundation,
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  #include "getfem/dal_singleton.h"
diff --cc src/getfem_model_solvers.cc
index b5290da,9ae7d63..313a148
--- a/src/getfem_model_solvers.cc
+++ b/src/getfem_model_solvers.cc
@@@ -156,64 -159,85 +159,144 @@@ namespace getfem 
        } else {
  	if (comp) compute_residual();
  	return residual_norm();
++<<<<<<< HEAD
 +      }
 +    }
 +
 +
 +    R line_search(VECTOR &dr, const gmm::iteration &iter) {
 +      size_type nit = 0;
 +      gmm::resize(stateinit, md.nb_dof());
 +      gmm::copy(state, stateinit);
 +      R alpha(1), res, res_init, R0;
 +	  
 +      res_init = res = compute_res(false);      
 +      // cout << "first residual = " << residual() << endl << endl;
 +      R0 = (is_reduced ? gmm::real(gmm::vect_sp(dr, rhsr))
 +	               : gmm::real(gmm::vect_sp(dr, rhs)));
 +
 +      // store the initial residual for the reprojection step.
 +//       size_type N = gmm::vect_size(residual());
 +//       VECTOR first_rhs(N); gmm::copy(residual(), first_rhs); // � �liminer
 +
 +
 +      // Compute the second derivative at alpha = 0 (value 2*a)
 +      // not very effective ... precision problem ?
 +      
 +//       R EPS = 1e-6;
 +//       gmm::add(gmm::sub_vector(stateinit, I), gmm::scaled(dr, EPS),
 +//                                               gmm::sub_vector(state, I));
 +//       R res2 = compute_res();
 +      
 +//       R a = (res2 + EPS * res - res) / gmm::sqr(EPS);
 +//       R delta = gmm::sqr(res)-R(4)*a*res;
 +//       R alpha_bis = R(1);
 +//       if (delta > 0) {
 +// 	R l1 = (res - sqrt(delta)) / (R(2)*a);
 +// 	R l2 = (res - sqrt(delta)) / (R(2)*a);
 +// 	if (l1 > 0) alpha_bis = std::min(alpha_bis, l1);
 +// 	if (l2 > 0) alpha_bis = std::min(alpha_bis, l2);
 +//       }
 +//       if (a > 0)
 +// 	alpha_bis = std::min(alpha_bis, res / (R(2)*a));
 +//       cout << "alpha_bis = " << alpha_bis << endl;
 +      
 +//       gmm::add(gmm::sub_vector(stateinit, I), gmm::scaled(dr, alpha_bis),
 +//                                               gmm::sub_vector(state, I));
 +
 +//       R res3 = compute_res();
 +//       cout << "res3 = " << res3 << endl;
 +
 +//       cout.precision(16);
 +//       cout << "res = " << res << " res2 = " << res2 << endl;
 +//       cout << "a = " << (res2 + EPS * res - res) / gmm::sqr(EPS) << endl;
 +//       cout << "aa = " << (res2 + EPS * res - res) << endl;
 +
 +      
++=======
+       }
+     }
+ 
+ 
+     R line_search(VECTOR &dr, const gmm::iteration &iter) {
+       size_type nit = 0;
+       gmm::resize(stateinit, md.nb_dof());
+       gmm::copy(state, stateinit);
+       R alpha(1), res, /* res_init, */ R0;
+ 	  
+       /* res_init = */ res = compute_res(false);      
+       // cout << "first residual = " << residual() << endl << endl;
+       R0 = (is_reduced ? gmm::real(gmm::vect_sp(dr, rhsr))
+ 	               : gmm::real(gmm::vect_sp(dr, rhs)));
+ 
+       // store the initial residual for the reprojection step.
+ //       size_type N = gmm::vect_size(residual());
+ //       VECTOR first_rhs(N); gmm::copy(residual(), first_rhs); // � �liminer
+ 
+ 
+       // Compute the second derivative at alpha = 0 (value 2*a)
+       // not very effective ... precision problem ?
+       
+ //       R EPS = 1e-6;
+ //       gmm::add(gmm::sub_vector(stateinit, I), gmm::scaled(dr, EPS),
+ //                                               gmm::sub_vector(state, I));
+ //       R res2 = compute_res();
+       
+ //       R a = (res2 + EPS * res - res) / gmm::sqr(EPS);
+ //       R delta = gmm::sqr(res)-R(4)*a*res;
+ //       R alpha_bis = R(1);
+ //       if (delta > 0) {
+ // 	R l1 = (res - sqrt(delta)) / (R(2)*a);
+ // 	R l2 = (res - sqrt(delta)) / (R(2)*a);
+ // 	if (l1 > 0) alpha_bis = std::min(alpha_bis, l1);
+ // 	if (l2 > 0) alpha_bis = std::min(alpha_bis, l2);
+ //       }
+ //       if (a > 0)
+ // 	alpha_bis = std::min(alpha_bis, res / (R(2)*a));
+ //       cout << "alpha_bis = " << alpha_bis << endl;
+       
+ //       gmm::add(gmm::sub_vector(stateinit, I), gmm::scaled(dr, alpha_bis),
+ //                                               gmm::sub_vector(state, I));
+ 
+ //       R res3 = compute_res();
+ //       cout << "res3 = " << res3 << endl;
+ 
+ //       cout.precision(16);
+ //       cout << "res = " << res << " res2 = " << res2 << endl;
+ //       cout << "a = " << (res2 + EPS * res - res) / gmm::sqr(EPS) << endl;
+ //       cout << "aa = " << (res2 + EPS * res - res) << endl;
+       
+ #if TRACE_SOL  
+       static int trace_number = 0;
+       int trace_iter = 0;
+       {
+ 	std::stringstream trace_name;
+ 	trace_name << "line_search_state" << std::setfill('0')
+ 		   << std::setw(3) << trace_number << "_000_init";
+ 	gmm::vecsave(trace_name.str(),stateinit);
+       }
+       trace_number++;
+ #endif 
+ 
++>>>>>>> upstream
        ls.init_search(res, iter.get_iteration(), R0);
        do {
  	alpha = ls.next_try();
  	gmm::add(gmm::sub_vector(stateinit, I), gmm::scaled(dr, alpha),
  		 gmm::sub_vector(state, I));
++<<<<<<< HEAD
++=======
+ #if TRACE_SOL
+ 	{
+ 	  trace_iter++;
+ 	  std::stringstream trace_name;
+ 	  trace_name  << "line_search_state" << std::setfill('0')
+ 		      << std::setw(3) << trace_number << "_"
+ 		      << std::setfill('0') << std::setw(3) << trace_iter;
+ 	  gmm::vecsave(trace_name.str(), state);
+ 	}
+ #endif 
++>>>>>>> upstream
  	res = compute_res();
  	// cout << "residual = " << residual() << endl << endl;
  	R0 = (is_reduced ? gmm::real(gmm::vect_sp(dr, rhsr))
diff --cc src/getfem_models.cc
index 2708039,1354115..e635d9a
--- a/src/getfem_models.cc
+++ b/src/getfem_models.cc
@@@ -1,3 -1,4 +1,7 @@@
++<<<<<<< HEAD
++=======
+ /* -*- c++ -*- (enables emacs c++ mode) */
++>>>>>>> upstream
  /*===========================================================================
   
   Copyright (C) 2009-2012 Yves Renard
@@@ -192,10 -200,10 +203,17 @@@ namespace getfem 
          it->second.partial_mf->adapt(alldof);
          it->second.set_size(it->second.partial_mf->nb_dof());
  
++<<<<<<< HEAD
 +        // Obtening the coupling matrix between the multipier and
 +        // the primal variable. A search is done on all the terms of the
 +        // model. Only the the corresponding linear terms are added.
 +	// If no linear term is available, a mass matrix is used.
++=======
+         // Obtaining the coupling matrix between the multipier and
+         // the primal variable. A search is done on all the terms of the
+         // model. Only the the corresponding linear terms are added.
+         // If no linear term is available, a mass matrix is used.
++>>>>>>> upstream
  
          gmm::col_matrix< gmm::rsvector<scalar_type> >
            MM(it2->second.mf->nb_dof(), it->second.mf->nb_dof());
@@@ -203,7 -211,7 +221,11 @@@
  
  	if (it->second.filter == VDESCRFILTER_CTERM) {
  
++<<<<<<< HEAD
 +	  for (size_type ib = 0; ib < bricks.size(); ++ib) {
++=======
+           for (dal::bv_visitor ib(valid_bricks); !ib.finished(); ++ib) {
++>>>>>>> upstream
  	    const brick_description &brick = bricks[ib];
  	    bool bupd = false;
  	    bool cplx = is_complex() && brick.pbr->is_complex();
@@@ -242,9 -250,24 +264,30 @@@
  	    }
  	  }
  
++<<<<<<< HEAD
 +	  if (!termadded) 
 +	    GMM_WARNING1("No term found to filter multiplier " << it->first
 +			 << ". Variable is cancelled");
++=======
+ 	  if (!termadded)
+ 	    GMM_WARNING1("No term found to filter multiplier " << it->first
+ 			 << ". Variable is cancelled");
+ #if GETFEM_PARA_LEVEL > 1
+ 	  if (termadded) {
+             // we assume that all bricks take mpi_region into account but it
+             // would be better if the brick itself could report if it supports
+             // distributed assembly
+             // This is only a reference implementation, it needs to be optimized
+             // maybe by using gmm::mpi_distributed_matrix
+             std::vector<scalar_type> tmpvec1(gmm::mat_nrows(MM)), tmpvec2(gmm::mat_nrows(MM));
+             for (size_type k = 0; k < gmm::mat_ncols(MM); ++k) {
+                 gmm::copy(gmm::mat_col(MM,k),tmpvec1);
+                 MPI_SUM_VECTOR(tmpvec1,tmpvec2);
+                 gmm::copy(tmpvec2,gmm::mat_col(MM,k));
+             }
+           }
+ #endif
++>>>>>>> upstream
  	} else if (it->second.filter == VDESCRFILTER_INFSUP) {
  	  asm_mass_matrix(MM, *(it->second.mim), *(it2->second.mf),
  			  *(it->second.mf), it->second.m_region);
@@@ -274,7 -297,7 +317,11 @@@
        }
  
        if (mults.size() > 1) {
++<<<<<<< HEAD
 +        range_basis(MGLOB, glob_columns, 1E-12, gmm::col_major(), true);
++=======
+         gmm::range_basis(MGLOB, glob_columns, 1E-12, gmm::col_major(), true);
++>>>>>>> upstream
  
          s = 0;
          for (size_type k = 0; k < mults.size(); ++k) {
@@@ -390,7 -413,7 +437,11 @@@
                                 dim_type qdim, size_type niter) {
      check_name_valitity(name);
      variables[name] = var_description(false, is_complex(), true, niter,
++<<<<<<< HEAD
 +                                      VDESCRFILTER_NO, &mf, 0, qdim);
++=======
+                                       VDESCRFILTER_NO, &mf, -1, qdim);
++>>>>>>> upstream
      variables[name].set_size(mf.nb_dof()*qdim);
      add_dependency(mf);
    }
@@@ -423,12 -535,18 +563,24 @@@
                               const varnamelist &datanames,
                               const termlist &terms,
                               const mimlist &mims, size_type region) {
++<<<<<<< HEAD
 +    bricks.push_back(brick_description(pbr, varnames, datanames, terms,
 +                                       mims, region));
 +    size_type ib = bricks.size() - 1;
++=======
+     size_type ib = valid_bricks.first_false();
+     if (ib == bricks.size())
+       bricks.push_back(brick_description(pbr, varnames, datanames, terms,
+                                          mims, region));
+     else
+       bricks[ib] = brick_description(pbr, varnames, datanames, terms,
+                                      mims, region);
++>>>>>>> upstream
      active_bricks.add(ib);
-     for  (size_type i = 0; i < bricks.back().mims.size(); ++i)
-       add_dependency(*(bricks.back().mims[i]));
+     valid_bricks.add(ib);
+     
+     for (size_type i = 0; i < bricks[ib].mims.size(); ++i)
+       add_dependency(*(bricks[ib].mims[i]));
  
      GMM_ASSERT1(pbr->is_real() || is_complex(),
                  "Impossible to add a complex brick to a real model");
@@@ -456,41 -574,39 +608,75 @@@
    }
  
    void model::add_mim_to_brick(size_type ib, const mesh_im &mim) {
++<<<<<<< HEAD
 +    GMM_ASSERT1(ib < bricks.size(), "Inexistent brick");
++=======
+     GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
++>>>>>>> upstream
      touch_brick(ib);
      bricks[ib].mims.push_back(&mim);
      add_dependency(mim);
    }
++<<<<<<< HEAD
 +
 +  void model::change_terms_of_brick(size_type ib, const termlist &terms) {
 +    GMM_ASSERT1(ib < bricks.size(), "Inexistent brick");
 +    touch_brick(ib);
 +    bricks[ib].tlist = terms;
 +    if (is_complex() && bricks[ib].pbr->is_complex()) {
 +      bricks.back().cmatlist.resize(terms.size());
 +      bricks.back().cveclist[0].resize(terms.size());
 +      bricks.back().cveclist_sym[0].resize(terms.size());
 +    } else {
 +      bricks.back().rmatlist.resize(terms.size());
 +      bricks.back().rveclist[0].resize(terms.size());
 +      bricks.back().rveclist_sym[0].resize(terms.size());
 +    }
 +  }
 +
 +  void model::change_variables_of_brick(size_type ib, const varnamelist &vl) {
 +    GMM_ASSERT1(ib < bricks.size(), "Inexistent brick");
 +    touch_brick(ib);
 +    bricks[ib].vlist = vl;
 +    for (size_type i=0; i < vl.size(); ++i)
 +      GMM_ASSERT1(variables.find(vl[i]) != variables.end(),
 +                  "Undefined model variable " << vl[i]);
 +  }
 +
 +
 +  void model::add_time_dispatcher(size_type ibrick, pdispatcher pdispatch) {
 +
 +    GMM_ASSERT1(ibrick < bricks.size(), "Inexistent brick");
++=======
+ 
+   void model::change_terms_of_brick(size_type ib, const termlist &terms) {
+     GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
+     touch_brick(ib);
+     bricks[ib].tlist = terms;
+     if (is_complex() && bricks[ib].pbr->is_complex()) {
+       bricks.back().cmatlist.resize(terms.size());
+       bricks.back().cveclist[0].resize(terms.size());
+       bricks.back().cveclist_sym[0].resize(terms.size());
+     } else {
+       bricks.back().rmatlist.resize(terms.size());
+       bricks.back().rveclist[0].resize(terms.size());
+       bricks.back().rveclist_sym[0].resize(terms.size());
+     }
+   }
++>>>>>>> upstream
+ 
+   void model::change_variables_of_brick(size_type ib, const varnamelist &vl) {
+     GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
+     touch_brick(ib);
+     bricks[ib].vlist = vl;
+     for (size_type i=0; i < vl.size(); ++i)
+       GMM_ASSERT1(variables.find(vl[i]) != variables.end(),
+                   "Undefined model variable " << vl[i]);
+   }
+ 
  
+   void model::add_time_dispatcher(size_type ibrick, pdispatcher pdispatch) {
+     GMM_ASSERT1(valid_bricks[ibrick], "Inexistent brick");
      pbrick pbr = bricks[ibrick].pbr;
  
      bricks[ibrick].pdispatch = pdispatch;
@@@ -517,11 -633,9 +703,14 @@@
      }
    }
  
- 
- 
    const std::string &model::varname_of_brick(size_type ind_brick,
++<<<<<<< HEAD
 +                                      size_type ind_var) {
 +    GMM_ASSERT1(ind_brick < bricks.size(), "Inexistent brick");
++=======
+ 					     size_type ind_var) {
+     GMM_ASSERT1(valid_bricks[ind_brick], "Inexistent brick");
++>>>>>>> upstream
      GMM_ASSERT1(ind_var < bricks[ind_brick].vlist.size(),
                 "Inexistent brick variable");
      return bricks[ind_brick].vlist[ind_var];
@@@ -529,7 -643,7 +718,11 @@@
  
    const std::string &model::dataname_of_brick(size_type ind_brick,
                                                size_type ind_data) {
++<<<<<<< HEAD
 +    GMM_ASSERT1(ind_brick < bricks.size(), "Inexistent brick");
++=======
+     GMM_ASSERT1(valid_bricks[ind_brick], "Inexistent brick");
++>>>>>>> upstream
      GMM_ASSERT1(ind_data < bricks[ind_brick].dlist.size(),
                  "Inexistent brick data");
      return bricks[ind_brick].dlist[ind_data];
@@@ -540,7 -654,7 +733,11 @@@
        ost << "Model with no bricks" << endl;
      else {
        ost << "List of model bricks:" << endl;
++<<<<<<< HEAD
 +      for (size_type i = 0; i < bricks.size(); ++i) {
++=======
+       for (dal::bv_visitor i(valid_bricks); !i.finished(); ++i) {
++>>>>>>> upstream
          ost << "Brick " << std::setw(3) << std::right << i + base_id
              << " " << std::setw(20) << std::right
              << bricks[i].pbr->brick_name();
@@@ -568,9 -682,12 +765,18 @@@
      // Initialization of vector and matrices.
      for (size_type j = 0; j < brick.tlist.size(); ++j) {
        const term_description &term = brick.tlist[j];
++<<<<<<< HEAD
 +      size_type nbd1 = variables[term.var1].size();
 +      size_type nbd2 = term.is_matrix_term ?
 +        variables[term.var2].size() : 0;
++=======
+       bool isg = term.is_global;
+       size_type nbgdof = is_complex() ?
+         gmm::vect_size(crhs) : gmm::vect_size(rrhs);
+       size_type nbd1 = isg ? nbgdof : variables[term.var1].size();
+       size_type nbd2 = isg ? nbgdof : (term.is_matrix_term ?
+                                       variables[term.var2].size() : 0);
++>>>>>>> upstream
        if (term.is_matrix_term &&
            (brick.pbr->is_linear() || (version | BUILD_MATRIX))) {
          if (version | BUILD_ON_DATA_CHANGE) {
@@@ -622,14 -817,39 +906,50 @@@
                                             brick.cveclist[rhs_ind],
                                             brick.cveclist_sym[rhs_ind],
                                             brick.region, version);
++<<<<<<< HEAD
 +    else
 +      brick.pbr->asm_real_tangent_terms(*this, ib, brick.vlist, brick.dlist,
 +                                        brick.mims,
 +                                        brick.rmatlist,
 +                                        brick.rveclist[rhs_ind],
 +                                        brick.rveclist_sym[rhs_ind],
 +                                        brick.region, version);
 +  }
++=======
+     else{
+ 
+         /*distributing the resulting vectors and matrices
+         for individual threads. This is done every time assembly is performed,
+         hence, not effective. Will try to include this distribution into the
+         brick description, to avoid their re-allocation (Andriy)*/
+ 	    list_distro<real_matlist> rmatlist(brick.rmatlist);
+ 	    list_distro<real_veclist> rveclist(brick.rveclist[rhs_ind]);
+ 	    list_distro<real_veclist> rveclist_sym(brick.rveclist_sym[rhs_ind]);
+ 
+ 
+         /*running the assembly in parallel*/
+ 	    gmm::standard_locale locale;
+ 	    open_mp_is_running_properly check; 
+ #pragma omp parallel default(shared)  
+             { 
+ #pragma omp for schedule(static) 
+             for(size_type i=0;i<num_threads();i++){
+                  brick.pbr->asm_real_tangent_terms(*this, ib, brick.vlist, brick.dlist,
+                                                 brick.mims,
+                                                 rmatlist,
+                                                 rveclist,
+                                                 rveclist_sym,
+                                                 brick.partition.thread_local_partition(), 
+                                                 version);
+                 }
+ 	     }
+         //the memory, allocated dynamically with boost::intrusive_pointer
+         //is realised only after this call. I hope this doesn't blow memory with some bricks
+ 	     dal::collect_static_stored_objects_garbage();
+          }
+ 
+  }
++>>>>>>> upstream
  
    void model::set_dispatch_coeff(void) {
      for (dal::bv_visitor ib(active_bricks); !ib.finished(); ++ib) {
@@@ -814,7 -1144,6 +1244,10 @@@
      if (brick.pbr->is_linear()) brick.terms_to_be_computed = false;
    }
  
++<<<<<<< HEAD
 +
++=======
++>>>>>>> upstream
  
    void model::linear_brick_add_to_rhs(size_type ib, size_type ind_data,
                                        size_type n_iter) const {
@@@ -825,58 -1154,93 +1258,147 @@@
  
        for (size_type j = 0; j < brick.tlist.size(); ++j) {
          const term_description &term = brick.tlist[j];
++<<<<<<< HEAD
 +
 +        size_type n_iter_1 = n_iter, n_iter_2 = n_iter;
 +        if (n_iter == size_type(-1)) {
++=======
+         bool isg = term.is_global;
+         size_type nbgdof = nb_dof();
+ 
+         size_type n_iter_1 = n_iter, n_iter_2 = n_iter;
+         if (!isg && n_iter == size_type(-1)) {
++>>>>>>> upstream
            n_iter_1 = variables[term.var1].default_iter;
            if (term.is_matrix_term)
              n_iter_2 = variables[term.var2].default_iter;
          }
++<<<<<<< HEAD
 +
 +        if (term.is_matrix_term) {
 +          if (cplx)
 +            gmm::mult_add
 +              (brick.cmatlist[j],
 +               gmm::scaled(variables[term.var2].complex_value[n_iter_2],
 +                           std::complex<scalar_type>(-1)),
 +               brick.cveclist[ind_data][j]);
 +          else
 +            gmm::mult_add
 +              (brick.rmatlist[j],
 +               gmm::scaled(variables[term.var2].real_value[n_iter_2],
 +                           scalar_type(-1)), brick.rveclist[ind_data][j]);
 +
 +          if (term.is_symmetric && term.var1.compare(term.var2)) {
 +            if (cplx)
 +              gmm::mult_add
 +                (gmm::conjugated(brick.cmatlist[j]),
 +                 gmm::scaled(variables[term.var1].complex_value[n_iter_1],
 +                             std::complex<scalar_type>(-1)),
 +                 brick.cveclist_sym[ind_data][j]);
 +            else
 +              gmm::mult_add
 +                (gmm::transposed(brick.rmatlist[j]),
 +                 gmm::scaled(variables[term.var1].real_value[n_iter_1],
 +                             scalar_type(-1)),
 +                 brick.rveclist_sym[ind_data][j]);
 +          }
 +        }
 +      }
 +    }
 +  }
 +
 +
 +  bool model::build_reduced_index(std::vector<size_type> &ind) {
 +    ind.resize(0);
 +    bool reduced = false;
 +    for (VAR_SET::iterator it = variables.begin(); it != variables.end(); ++it)
 +      if (it->second.is_variable) {
 +	if  (it->second.is_disabled)
 +	  reduced = true;
 +	else {
 +	  for (size_type i=it->second.I.first(); i < it->second.I.last(); ++i)
 +	    ind.push_back(i);
 +	}
++=======
+         
+         
+ 
+         if (term.is_matrix_term) {
+           if (cplx) {
+             if (isg) {
+               model_complex_plain_vector V(nbgdof);
+               for (VAR_SET::iterator it = variables.begin();
+                    it != variables.end(); ++it) 
+                 if (it->second.is_variable) {
+                   size_type n_iter_i = (n_iter == size_type(-1))
+                     ? it->second.default_iter : n_iter;
+                   gmm::copy(it->second.complex_value[n_iter_i],
+                             gmm::sub_vector(V, it->second.I));
+                 }
+               gmm::mult_add
+                 (brick.cmatlist[j],
+                  gmm::scaled(V,  std::complex<scalar_type>(-1)),
+                  brick.cveclist[ind_data][j]);
+             } else
+               gmm::mult_add
+                 (brick.cmatlist[j],
+                  gmm::scaled(variables[term.var2].complex_value[n_iter_2],
+                              std::complex<scalar_type>(-1)),
+                  brick.cveclist[ind_data][j]);
+           }
+           else {
+             if (isg) {
+               model_real_plain_vector V(nbgdof);
+               for (VAR_SET::iterator it = variables.begin();
+                    it != variables.end(); ++it) 
+                 if (it->second.is_variable) {
+                   size_type n_iter_i = (n_iter == size_type(-1))
+                     ? it->second.default_iter : n_iter;
+                   gmm::copy(it->second.real_value[n_iter_i],
+                             gmm::sub_vector(V, it->second.I));
+                 }
+               gmm::mult_add
+                 (brick.rmatlist[j], gmm::scaled(V,  scalar_type(-1)),
+                  brick.rveclist[ind_data][j]);
+             } else
+               gmm::mult_add
+                 (brick.rmatlist[j],
+                  gmm::scaled(variables[term.var2].real_value[n_iter_2],
+                              scalar_type(-1)), brick.rveclist[ind_data][j]);
+           }
+ 
+           if (term.is_symmetric && term.var1.compare(term.var2)) {
+             if (cplx)
+               gmm::mult_add
+                 (gmm::conjugated(brick.cmatlist[j]),
+                  gmm::scaled(variables[term.var1].complex_value[n_iter_1],
+                              std::complex<scalar_type>(-1)),
+                  brick.cveclist_sym[ind_data][j]);
+             else
+               gmm::mult_add
+                 (gmm::transposed(brick.rmatlist[j]),
+                  gmm::scaled(variables[term.var1].real_value[n_iter_1],
+                              scalar_type(-1)),
+                  brick.rveclist_sym[ind_data][j]);
+           }
+         }
++>>>>>>> upstream
+       }
 -    }
++    return reduced;
+   }
+ 
+ 
+   bool model::build_reduced_index(std::vector<size_type> &ind) {
+     ind.resize(0);
+     bool reduced = false;
+     for (VAR_SET::iterator it = variables.begin(); it != variables.end(); ++it)
+       if (it->second.is_variable) {
+ 	if  (it->second.is_disabled)
+ 	  reduced = true;
+ 	else {
+ 	  for (size_type i=it->second.I.first(); i < it->second.I.last(); ++i)
+ 	    ind.push_back(i);
+ 	}
        }
      return reduced;
    }
@@@ -926,11 -1291,11 +1449,19 @@@
            pseudop = brick.pbr->asm_real_pseudo_potential
              (*this, ib, brick.vlist, brick.dlist, brick.mims, brick.rmatlist,
               brick.rveclist[0], brick.rveclist_sym[0], brick.region);
++<<<<<<< HEAD
 +
 +        pseudo_potential_ += pseudop * coeff0;
 +
 +        GMM_ASSERT1(!(brick.pdispatch),
 +                    "Pseudo potential not supported by brick dispatcher, sorry");
++=======
+ 
+         pseudo_potential_ += pseudop * coeff0;
+ 
+         GMM_ASSERT1(!(brick.pdispatch), "Pseudo potential not "
+                     "supported by brick dispatcher, sorry");
++>>>>>>> upstream
  
        }
  
@@@ -938,9 -1303,11 +1469,17 @@@
  
        for (size_type j = 0; j < brick.tlist.size(); ++j) {
          term_description &term = brick.tlist[j];
++<<<<<<< HEAD
 +        gmm::sub_interval I1 = variables[term.var1].I;
 +        gmm::sub_interval I2(0,0);
 +        if (term.is_matrix_term) I2 = variables[term.var2].I;
++=======
+         bool isg = term.is_global;
+         size_type nbgdof = nb_dof();
+         gmm::sub_interval I1(0,nbgdof), I2(0,nbgdof);
+         if (!isg) I1 = variables[term.var1].I;
+         if (term.is_matrix_term && !isg) I2 = variables[term.var2].I;
++>>>>>>> upstream
  
          if (cplx) {
            if (term.is_matrix_term && (version & BUILD_MATRIX)) {
@@@ -962,7 -1329,15 +1501,19 @@@
                gmm::add(brick.cveclist[0][j], gmm::sub_vector(crhs, I1));
              if (term.is_matrix_term && brick.pbr->is_linear()
                  && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
++<<<<<<< HEAD
 +              gmm::mult_add(brick.cmatlist[j],
++=======
+               if (isg) {
+                 model_complex_plain_vector V(nbgdof);
+                 from_variables(V);
+                 gmm::mult_add(brick.cmatlist[j],
+                             gmm::scaled(V, std::complex<scalar_type>(-coeff0)),
+                             crhs);
+               }
+               else
+                 gmm::mult_add(brick.cmatlist[j],
++>>>>>>> upstream
                              gmm::scaled(variables[term.var2].complex_value[0],
                                          std::complex<scalar_type>(-coeff0)),
                              gmm::sub_vector(crhs, I1));
@@@ -981,7 -1356,7 +1532,11 @@@
                   gmm::mult_add(gmm::conjugated(brick.cmatlist[j]),
                              gmm::scaled(variables[term.var1].complex_value[0],
                                          std::complex<scalar_type>(-coeff0)),
++<<<<<<< HEAD
 +                               gmm::sub_vector(crhs, I2));
++=======
+                             gmm::sub_vector(crhs, I2));
++>>>>>>> upstream
                 }
              }
            }
@@@ -1005,7 -1380,15 +1560,19 @@@
                gmm::add(brick.rveclist[0][j], gmm::sub_vector(crhs, I1));
              if (term.is_matrix_term && brick.pbr->is_linear()
                  && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
++<<<<<<< HEAD
 +              gmm::mult_add(brick.rmatlist[j],
++=======
+               if (isg) {
+                 model_complex_plain_vector V(nbgdof);
+                 from_variables(V);
+                 gmm::mult_add(brick.rmatlist[j],
+                             gmm::scaled(V, std::complex<scalar_type>(-coeff0)),
+                             crhs);
+               }
+               else
+                 gmm::mult_add(brick.rmatlist[j],
++>>>>>>> upstream
                              gmm::scaled(variables[term.var2].complex_value[0],
                                          std::complex<scalar_type>(-coeff0)),
                              gmm::sub_vector(crhs, I1));
@@@ -1048,6 -1431,12 +1615,15 @@@
                gmm::add(brick.rveclist[0][j], gmm::sub_vector(rrhs, I1));
              if (term.is_matrix_term && brick.pbr->is_linear()
                  && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
++<<<<<<< HEAD
++=======
+               if (isg) {
+                 model_real_plain_vector V(nbgdof);
+                 from_variables(V);
+                 gmm::mult_add(brick.rmatlist[j],
+                               gmm::scaled(V, -coeff0), rrhs);
+               }
++>>>>>>> upstream
                gmm::mult_add(brick.rmatlist[j],
                              gmm::scaled(variables[term.var2].real_value[0],
                                          -coeff0),
@@@ -1085,7 -1474,126 +1661,129 @@@
  //           brick.rmatlist = real_matlist(brick.tlist.size());
  //           brick.rveclist[0] = real_veclist(brick.tlist.size());
  //         }
++<<<<<<< HEAD
++=======
+ 
+     }
+ 
+     if (version & BUILD_RHS) {
+       if (is_complex()) MPI_SUM_VECTOR(crhs); else MPI_SUM_VECTOR(rrhs);
+     }
+ 
++>>>>>>> upstream
+ 
+     // Post simplification for dof constraints
+     if ((version & BUILD_RHS) || (version & BUILD_MATRIX)) {
+       if (is_complex()) {
+         std::vector<size_type> dof_indices;
+         std::vector<complex_type> dof_pr_values;
+         std::vector<complex_type> dof_go_values;
+         std::map<std::string, complex_dof_constraints_var>::const_iterator it;
+         
+         for (it = complex_dof_constraints.begin();
+              it != complex_dof_constraints.end(); ++it) {
+           const gmm::sub_interval &I = interval_of_variable(it->first);
+           const model_complex_plain_vector &V = complex_variable(it->first);
+           complex_dof_constraints_var::const_iterator itv;
+           for (itv = it->second.begin(); itv != it->second.end(); ++itv) {
+             dof_indices.push_back(itv->first + I.first());
+             dof_go_values.push_back(itv->second);
+             dof_pr_values.push_back(V[itv->first]);
+           }
+         }
+         
+         if (dof_indices.size()) {
+           gmm::sub_index SI(dof_indices);
+           gmm::sub_interval II(0, nb_dof());
+           
+           if (version & BUILD_RHS) {
+             if (is_linear_) {
+               if (is_symmetric_) {
+                 scalar_type valnorm = gmm::vect_norm2(dof_go_values);
+                 if (valnorm > scalar_type(0)) {
+                   GMM_ASSERT1(version & BUILD_MATRIX, "Rhs only for a "
+                               "symmetric linear problem with dof "
+                               "constraint not allowed");
+                   model_complex_plain_vector vv(gmm::vect_size(rrhs));
+                   gmm::mult(gmm::sub_matrix(cTM, II, SI), dof_go_values, vv);
+                   MPI_SUM_VECTOR(vv);
+                   gmm::add(gmm::scaled(vv, scalar_type(-1)), crhs);
+                 }
+               }
+               gmm::copy(dof_go_values, gmm::sub_vector(crhs, SI));
+             } else {
+               gmm::add(dof_go_values,
+                        gmm::scaled(dof_pr_values, complex_type(-1)),
+                        gmm::sub_vector(crhs, SI));
+             }
+           }
+           if (version & BUILD_MATRIX) {
+             gmm::clear(gmm::sub_matrix(cTM, SI, II));
+             if (is_symmetric_) gmm::clear(gmm::sub_matrix(cTM, II, SI));
+ 
+             if (MPI_IS_MASTER()) {
+               for (size_type i = 0; i < dof_indices.size(); ++i)
+                 cTM(dof_indices[i], dof_indices[i]) = complex_type(1);
+             }
+           }
+         }
+       } else {
+         std::vector<size_type> dof_indices;
+         std::vector<scalar_type> dof_pr_values;
+         std::vector<scalar_type> dof_go_values;
+         std::map<std::string, real_dof_constraints_var>::const_iterator it;
+         
+         for (it = real_dof_constraints.begin();
+              it != real_dof_constraints.end(); ++it) {
+           const gmm::sub_interval &I = interval_of_variable(it->first);
+           const model_real_plain_vector &V = real_variable(it->first);
+           real_dof_constraints_var::const_iterator itv;
+           for (itv = it->second.begin(); itv != it->second.end(); ++itv) {
+             dof_indices.push_back(itv->first + I.first());
+             dof_go_values.push_back(itv->second);
+             dof_pr_values.push_back(V[itv->first]);
+           }
+         }
+         // In parallel, a unification of the indices and values could be done
+         // in order to allow the bricks to compute dof constraints in a
+         // distributed way. Not done for the moment.
+         
+         if (dof_indices.size()) {
+           gmm::sub_index SI(dof_indices);
+           gmm::sub_interval II(0, nb_dof());
+           
+           if (version & BUILD_RHS) {
+             if (is_linear_) {
+               if (is_symmetric_) {
+                 scalar_type valnorm = gmm::vect_norm2(dof_go_values);
+                 if (valnorm > scalar_type(0)) {
+                   GMM_ASSERT1(version & BUILD_MATRIX, "Rhs only for a "
+                               "symmetric linear problem with dof "
+                               "constraint not allowed");
+                   model_real_plain_vector vv(gmm::vect_size(rrhs));
+                   gmm::mult(gmm::sub_matrix(rTM, II, SI), dof_go_values, vv);
+                   MPI_SUM_VECTOR(vv);
+                   gmm::add(gmm::scaled(vv, scalar_type(-1)), rrhs);
+                 }
+               }
+               gmm::copy(dof_go_values, gmm::sub_vector(rrhs, SI));
+             } else {
+               gmm::add(dof_go_values,
+                        gmm::scaled(dof_pr_values, scalar_type(-1)),
+                        gmm::sub_vector(rrhs, SI));
+             }
+           }
+           if (version & BUILD_MATRIX) {
+             gmm::clear(gmm::sub_matrix(rTM, SI, II));
+             if (is_symmetric_) gmm::clear(gmm::sub_matrix(rTM, II, SI));
  
+             if (MPI_IS_MASTER()) {
+               for (size_type i = 0; i < dof_indices.size(); ++i)
+                 rTM(dof_indices[i], dof_indices[i]) = scalar_type(1);
+             }
+           }
+         }
+       }
      }
    }
  
@@@ -1109,7 -1618,7 +1808,11 @@@
      GMM_ASSERT1(it!=variables.end(), "Undefined variable " << name);
      if (niter == size_type(-1)) niter = it->second.default_iter;
      GMM_ASSERT1(it->second.n_iter + it->second.n_temp_iter > niter,
++<<<<<<< HEAD
 +                "Unvalid iteration number "
++=======
+                 "Invalid iteration number "
++>>>>>>> upstream
                  << niter << " for " << name);
      return it->second.real_value[niter];
    }
@@@ -1122,7 -1631,7 +1825,11 @@@
      GMM_ASSERT1(it!=variables.end(), "Undefined variable " << name);
      if (niter == size_type(-1)) niter = it->second.default_iter;
      GMM_ASSERT1(it->second.n_iter + it->second.n_temp_iter  > niter,
++<<<<<<< HEAD
 +                "Unvalid iteration number "
++=======
+                 "Invalid iteration number "
++>>>>>>> upstream
                  << niter << " for " << name);
      return it->second.complex_value[niter];
    }
@@@ -1136,7 -1645,7 +1843,11 @@@
      it->second.v_num_data = act_counter();
      if (niter == size_type(-1)) niter = it->second.default_iter;
      GMM_ASSERT1(it->second.n_iter + it->second.n_temp_iter > niter,
++<<<<<<< HEAD
 +                "Unvalid iteration number "
++=======
+                 "Invalid iteration number "
++>>>>>>> upstream
                  << niter << " for " << name);
      return it->second.real_value[niter];
    }
@@@ -1150,7 -1659,7 +1861,11 @@@
      it->second.v_num_data = act_counter();
      if (niter == size_type(-1)) niter = it->second.default_iter;
      GMM_ASSERT1(it->second.n_iter + it->second.n_temp_iter > niter,
++<<<<<<< HEAD
 +                "Unvalid iteration number "
++=======
+                 "Invalid iteration number "
++>>>>>>> upstream
                  << niter << " for " << name);
      return it->second.complex_value[niter];
    }
@@@ -1161,7 -1670,7 +1876,11 @@@
  	  const brick_description &brick = bricks[ind_brick];
  	  update_brick(ind_brick, model::BUILD_ALL);
  
++<<<<<<< HEAD
 +	  brick.pbr->check_stiffness_matrix_and_rhs(*this, ind_brick, 
++=======
+       brick.pbr->check_stiffness_matrix_and_rhs(*this, ind_brick, brick.tlist,
++>>>>>>> upstream
  		  brick.vlist, brick.dlist, brick.mims, brick.rmatlist,
              brick.rveclist[0], brick.rveclist_sym[0], brick.region);
    }
@@@ -1174,87 -1683,137 +1893,221 @@@
    //
    //
    // ----------------------------------------------------------------------
++<<<<<<< HEAD
 +  	void virtual_brick::check_stiffness_matrix_and_rhs(const model &md, size_type s,
 +                                        const model::varnamelist &vl,
 +                                        const model::varnamelist &dl,
 +                                        const model::mimlist &mims,
 +                                        model::real_matlist &matl,
 +                                        model::real_veclist &rvc1,
 +                                        model::real_veclist &rvc2, 
 +										size_type rg,
 +										const scalar_type TINY) const
 +	{
 +		asm_real_tangent_terms(md, s, vl, dl, mims, matl, rvc1, rvc2, rg, model::BUILD_MATRIX);
 +		model_real_sparse_matrix SM(matl[0]);
 +		gmm::fill(rvc1[0], 0.0);
 +		asm_real_tangent_terms(md, s, vl, dl, mims, matl, rvc1, rvc2, rg, model::BUILD_RHS);
 +		model_real_plain_vector RHS0(rvc1[0]);
 +
 +		//finite difference stiffness		
 +		model_real_sparse_matrix fdSM(matl[0].nrows(),matl[0].ncols());
 +
 +		for (size_type i=0;i<rvc1[0].size();i++){
 +			model_real_plain_vector U(md.real_variable(vl[0]));
 +			U[i]+=TINY;
 +			gmm::copy(U, md.set_real_variable(vl[0]));
 +			gmm::fill(rvc1[0], 0.0);
 +			asm_real_tangent_terms(md, s, vl, dl, mims, matl, rvc1, rvc2, rg, model::BUILD_RHS);
 +			model_real_plain_vector RHS1(rvc1[0]);
 +			for (size_type j=0;j<rvc1[0].size();j++){
 +    			fdSM(i,j)=(RHS0[j]-RHS1[j])/TINY;
 +			}
 +			U[i]-=TINY;
 +			gmm::copy(U, md.set_real_variable(vl[0]));
 +		}
 +		model_real_sparse_matrix diffSM(matl[0].nrows(),matl[0].ncols());
 +		gmm::add(matl[0],gmm::scaled(fdSM,-1.0),diffSM);
 +		scalar_type norm_error_euc = gmm::mat_euclidean_norm(diffSM)/gmm::mat_euclidean_norm(matl[0])*100;
 +		scalar_type norm_error_1 = gmm::mat_norm1(diffSM)/gmm::mat_norm1(matl[0])*100;
 +		scalar_type norm_error_max = gmm::mat_maxnorm(diffSM)/gmm::mat_maxnorm(matl[0])*100;
 +		
 +		model_real_sparse_matrix diffSMtransposed(matl[0].nrows(),matl[0].ncols());
 +		gmm::add(gmm::transposed(fdSM),gmm::scaled(fdSM,-1.0),diffSMtransposed);
 +		scalar_type nsym_norm_error_euc = gmm::mat_euclidean_norm(diffSMtransposed)/gmm::mat_euclidean_norm(fdSM)*100;
 +		scalar_type nsym_norm_error_1 = gmm::mat_norm1(diffSMtransposed)/gmm::mat_norm1(fdSM)*100;
 +		scalar_type nsym_norm_error_max = gmm::mat_maxnorm(diffSMtransposed)/gmm::mat_maxnorm(fdSM)*100;
 +
 +		//print matrix if the size is small
 +		if(rvc1[0].size()<8){
 +			std::cout << "RHS Stiffness Matrix: \n";
 +			std::cout << "------------------------\n";
 +			for(size_type i=0; i < rvc1[0].size(); ++i){
 +				std::cout << "[";
 +				for(size_type j=0; j < rvc1[0].size(); ++j){
 +					std::cout << fdSM(i,j) << "  ";
 +				}
 +				std::cout << "]\n";
 +			}
 +			std::cout << "Analytical Stiffness Matrix: \n";
 +			std::cout << "------------------------\n";
 +			for(size_type i=0; i < rvc1[0].size(); ++i){
 +				std::cout << "[";
 +				for(size_type j=0; j < rvc1[0].size(); ++j){
 +					std::cout << matl[0](i,j) << "  ";
 +				}
 +				std::cout << "]\n";
 +			}
 +			std::cout << "Vector U: \n";
 +			std::cout << "------------------------\n";
 +			for(size_type i=0; i < rvc1[0].size(); ++i){
 +				std::cout << "[";
 +					std::cout << md.real_variable(vl[0])[i] << "  ";
 +				std::cout << "]\n";
 +			}
 +		}
 +
 +		std::cout<<"\n\nfinite diff test error_norm_eucl: "<<norm_error_euc <<"%"<<std::endl;
 +		std::cout<<"finite diff test error_norm1: "<<norm_error_1 <<"%"<<std::endl;
 +		std::cout<<"finite diff test error_max_norm: "<<norm_error_max <<"%"<<std::endl;
 +		std::cout<<"\n\nNonsymmetrical test error_norm_eucl: "<<nsym_norm_error_euc <<"%"<<std::endl;
 +		std::cout<<"Nonsymmetrical test error_norm1: "<<nsym_norm_error_1 <<"%"<<std::endl;
 +		std::cout<<"Nonsymmetrical test error_max_norm: "<<nsym_norm_error_max <<"%"<<std::endl;
 +	}
 +
++=======
+     void virtual_brick::check_stiffness_matrix_and_rhs
+         (const model &md, size_type s,
+         const model::termlist& tlist,
+         const model::varnamelist &vl,
+         const model::varnamelist &dl,
+         const model::mimlist &mims,
+         model::real_matlist &matl,
+         model::real_veclist &rvc1,
+         model::real_veclist &rvc2, 
+         size_type rg,
+         const scalar_type TINY) const {
+             std::cout<<"******Verifying stiffnesses of *******"<<std::endl;
+             std::cout<<"*** "<<brick_name()<<std::endl;
+ 
+             //Build the index for the corresponding RHS
+             std::map<std::string,size_type> rhs_index;
+             for(size_type iterm=0;iterm<matl.size();iterm++)
+                 if (tlist[iterm].var1==tlist[iterm].var2) rhs_index[tlist[iterm].var1]=iterm;
+ 
+             if (rhs_index.size()==0){
+                 GMM_WARNING0("*** cannot verify stiffness for this brick***");
+                 return;
+             }
+             asm_real_tangent_terms(md, s, vl, dl, mims, matl, rvc1, rvc2,
+                 rg, model::BUILD_MATRIX);
+             for(size_type iterm=0;iterm<matl.size();iterm++){
+ 
+                 std::cout<<std::endl;
+                 std::cout<<"    Stiffness["<<tlist[iterm].var1
+                     <<","<<tlist[iterm].var2<<"]:"<<std::endl;
+                 if (md.real_variable(tlist[iterm].var1).size()==0)
+                 {
+                     std::cout<<"    "<<tlist[iterm].var1<<" has zero size. Skipping this term"<<std::endl;
+                     continue;
+                 }
+                 if (md.real_variable(tlist[iterm].var2).size()==0)
+                 {
+                     std::cout<<"    "<<tlist[iterm].var2<<" has zero size. Skipping this term"<<std::endl;
+                     continue;
+                 }
+ 
+                 model_real_sparse_matrix SM(matl[iterm]);
+                 gmm::fill(rvc1[rhs_index[tlist[iterm].var1]], 0.0);
+                 asm_real_tangent_terms(md, s, vl, dl, mims, matl, rvc1, rvc2,
+                     rg, model::BUILD_RHS);
+                 if (gmm::mat_euclidean_norm(matl[iterm])<1e-12){
+                     std::cout<<"    The assembled matrix is nearly zero, skipping."<<std::endl;
+                     continue;
+                 }
+                 model_real_plain_vector RHS0(rvc1[rhs_index[tlist[iterm].var1]]);
+ 
+                 //finite difference stiffness		
+                 model_real_sparse_matrix fdSM(matl[iterm].nrows(),matl[iterm].ncols());
+                 model_real_plain_vector&U = md.set_real_variable(tlist[iterm].var2);
+                 model_real_plain_vector& RHS1 =rvc1[rhs_index[tlist[iterm].var1]];
+                 for (size_type j=0; j < matl[iterm].ncols(); j++){
+                     U[j]+=TINY;
+                     gmm::fill(RHS1, 0.0);
+                     asm_real_tangent_terms(md, s, vl, dl, mims, matl, rvc1, rvc2,
+                         rg, model::BUILD_RHS);
+                     for (size_type i=0;i<matl[iterm].nrows();i++)
+                         fdSM(i,j) = (RHS0[i]-RHS1[i])/TINY;
+                     U[j]-=TINY;
+                 }
+ 
+                 model_real_sparse_matrix diffSM(matl[iterm].nrows(),matl[iterm].ncols());
+                 gmm::add(SM,gmm::scaled(fdSM,-1.0),diffSM);
+                 scalar_type norm_error_euc
+                     = gmm::mat_euclidean_norm(diffSM)/gmm::mat_euclidean_norm(SM)*100;
+                 scalar_type norm_error_1
+                     = gmm::mat_norm1(diffSM)/gmm::mat_norm1(SM)*100;
+                 scalar_type norm_error_max
+                     = gmm::mat_maxnorm(diffSM)/gmm::mat_maxnorm(SM)*100;
+ 
+                 //checking symmetry of diagonal terms
+                 scalar_type nsym_norm_error_euc=0.0;
+                 scalar_type nsym_norm_error_1=0.0;
+                 scalar_type nsym_norm_error_max=0.0;
+                 if (tlist[iterm].var1==tlist[iterm].var2){
+                     model_real_sparse_matrix diffSMtransposed(matl[iterm].nrows(),matl[iterm].ncols());
+                     gmm::add(gmm::transposed(fdSM),gmm::scaled(fdSM,-1.0),diffSMtransposed);
+                     nsym_norm_error_euc
+                         = gmm::mat_euclidean_norm(diffSMtransposed)/gmm::mat_euclidean_norm(fdSM)*100;
+                     nsym_norm_error_1
+                         = gmm::mat_norm1(diffSMtransposed)/gmm::mat_norm1(fdSM)*100;
+                     nsym_norm_error_max
+                         = gmm::mat_maxnorm(diffSMtransposed)/gmm::mat_maxnorm(fdSM)*100;
+                 }
+ 
+                 //print matrix if the size is small
+                 if(rvc1[0].size()<8){
+                     std::cout << "RHS Stiffness Matrix: \n";
+                     std::cout << "------------------------\n";
+                     for(size_type i=0; i < rvc1[iterm].size(); ++i){
+                         std::cout << "[";
+                         for(size_type j=0; j < rvc1[iterm].size(); ++j){
+                             std::cout << fdSM(i,j) << "  ";
+                         }
+                         std::cout << "]\n";
+                     }
+                     std::cout << "Analytical Stiffness Matrix: \n";
+                     std::cout << "------------------------\n";
+                     for(size_type i=0; i < rvc1[iterm].size(); ++i){
+                         std::cout << "[";
+                         for(size_type j=0; j < rvc1[iterm].size(); ++j){
+                             std::cout << matl[iterm](i,j) << "  ";
+                         }
+                         std::cout << "]\n";
+                     }
+                     std::cout << "Vector U: \n";
+                     std::cout << "------------------------\n";
+                     for(size_type i=0; i < rvc1[iterm].size(); ++i){
+                         std::cout << "[";
+                         std::cout << md.real_variable(tlist[iterm].var2)[i] << "  ";
+                         std::cout << "]\n";
+                     }
+                 }
+                 std::cout
+                     << "\n\nfinite diff test error_norm_eucl: " << norm_error_euc << "%\n"
+                     << "finite diff test error_norm1: " << norm_error_1 << "%\n"
+                     << "finite diff test error_max_norm: " << norm_error_max << "%\n\n\n";
+ 
+                 if (tlist[iterm].var1==tlist[iterm].var2){
+                 std::cout
+                     << "Nonsymmetrical test error_norm_eucl: "<< nsym_norm_error_euc<< "%\n"
+                     << "Nonsymmetrical test error_norm1: " << nsym_norm_error_1 << "%\n"
+                     << "Nonsymmetrical test error_max_norm: " << nsym_norm_error_max << "%"
+                     << std::endl;
+                 }
+             }
+     }
++>>>>>>> upstream
  
    // ----------------------------------------------------------------------
    //
@@@ -1262,9 -1821,198 +2115,202 @@@
    //
    // ----------------------------------------------------------------------
  
+ 
+   struct generic_elliptic_Neumann_elem_term : public Neumann_elem_term {
+ 
+     const mesh_fem *mf_a;
+     const model_real_plain_vector *A;
+ 
+     mutable fem_interpolation_context ctx_a;
+     mutable base_vector coeff, val;
+     mutable base_matrix grad, G;
+ 
+     void compute_Neumann_term
+     (int version, const mesh_fem &mfvar, const model_real_plain_vector &var,
+      fem_interpolation_context& ctx, base_small_vector &n,
+      base_tensor &output, size_type /*auxilliary_ind*/ = 0) const {
+ 
+       if (version == 3) return;  // No contribution because the term is linear
+ 
+       const mesh &m = mfvar.linked_mesh();
+       size_type N = m.dim(), Q = mfvar.get_qdim(), s = 1, cv=ctx.convex_num();
+ 
+       if (A) {
+ 	s = gmm::vect_size(*A);
+         if (mf_a) s = s * mf_a->get_qdim() / mf_a->nb_dof();
+       }
+       gmm::resize(val, s);
+ 
+       if (mf_a) {
+ 	GMM_ASSERT1(!(mf_a->is_reduced()),
+ 		    "Sorry, to be adapted for reduced mesh fems");
+ 
+ 	if (!(ctx_a.have_pf()) || ctx_a.convex_num() != cv
+ 	    || (ctx_a.have_pfp() != ctx.have_pfp())
+ 	    || (ctx_a.have_pfp()
+ 		&& (&(ctx.pfp()->get_point_tab())
+ 		    != &(ctx_a.pfp()->get_point_tab())))) {
+ 
+ 	  bgeot::vectors_to_base_matrix
+ 	    (G, mf_a->linked_mesh().points_of_convex(cv));
+ 	  
+ 	  pfem_precomp pfp = fem_precomp(mf_a->fem_of_element(cv),
+ 					 &(ctx.pfp()->get_point_tab()), 0);
+ 
+ 	  if (ctx.have_pfp())
+ 	    ctx_a = fem_interpolation_context
+ 	      (mf_a->linked_mesh().trans_of_convex(cv), pfp, ctx.ii(),
+ 	       G, cv, ctx.face_num());
+ 	  else
+ 	    ctx_a = fem_interpolation_context
+ 	      (mf_a->linked_mesh().trans_of_convex(cv),
+ 	       mf_a->fem_of_element(cv), ctx.xref(), G, cv, ctx.face_num());
+ 
+ 	} else {
+ 	  if (ctx.have_pfp())  ctx_a.set_ii(ctx.ii());
+ 	  else ctx_a.set_xref(ctx.xref());
+ 	}
+ 
+ 	coeff.resize(mf_a->nb_basic_dof_of_element(cv));
+ 	gmm::copy(gmm::sub_vector(var, gmm::sub_index
+ 			      (mfvar.ind_basic_dof_of_element(cv))), coeff);
+ 	ctx_a.pf()->interpolation(ctx_a, coeff, val, dim_type(s));
+       } else if (A) {
+ 	gmm::copy(*A, val);
+       } else {
+ 	val[0] = scalar_type(1);
+       }
+ 
+       switch (version) {
+       case 1:
+ 	gmm::resize(grad, Q, N);
+ 	coeff.resize(mfvar.nb_basic_dof_of_element(cv));
+ 	gmm::copy(gmm::sub_vector(var, gmm::sub_index
+ 			      (mfvar.ind_basic_dof_of_element(cv))), coeff);
+ 	ctx.pf()->interpolation_grad(ctx, coeff, grad, dim_type(Q));
+ 
+ 	if (s == 1)
+ 	  gmm::mult_add(grad, gmm::scaled(n, val[0]), output.as_vector());
+ 	else if (s == N*N) {
+ 	  base_vector::const_iterator it = val.begin();
+ 	  for (size_type j = 0; j < N; ++j)
+ 	    for (size_type i = 0; i < N; ++i, ++it)
+ 	      for (size_type k = 0; k < Q; ++k)
+ 		output[k] += (*it)*grad(k,j)*n[i];
+ 	}
+ 	else if (s == N*N*Q*Q) {
+ 	  base_vector::const_iterator it = val.begin();
+ 	  for (size_type l = 0; l < N; ++l)
+ 	    for (size_type k = 0; k < Q; ++k)
+ 	      for (size_type j = 0; j < N; ++j)
+ 		for (size_type i = 0; i < Q; ++i, ++it)
+ 		  output[i] += (*it) * grad(k, l) * n[j];
+ 	}
+ 	break;
+       case 2:
+ 	{
+ 	  base_tensor t;
+ 	  dim_type tdim = ctx.pf()->target_dim(), qmult = dim_type(Q) / tdim;
+ 	  size_type ndof = ctx.pf()->nb_dof(cv);
+ 	  // The return tensor is t(i,j,k) with 0<=i<ndof, 0<=j<target_dim,
+ 	  // 0<=k<dim. In order to iterate on the tensor values, i should
+ 	  // increment the faster, then j, then k.
+ 	  // If target_dim == qdim, grad(phi_i)(j,k) = t(i,j,k)
+ 	  // If target_dim == 1, grad(phi_i * e_l)(l,k) = t(i,1,k)
+ 	  // General case, psi_{i*qmult+l} = phi_i * e_l  and
+ 	  //    grad(psi_{i*qmult+l})(j+tdim*l,k) = t(i,j,k)
+ 	  ctx.pf()->real_grad_base_value(ctx, t);
+ 
+ 	  if (s == 1) {
+ // 	    for (size_type l = 0; l < qmult; ++l) {
+ // 	      for (size_type p = 0; p < Q; ++p) {
+ // 		base_tensor::const_iterator it = t.begin();
+ // 		for (size_type k = 0; k < Q; ++k)
+ // 		  for (size_type j = 0; j < tdim; ++j)
+ // 		    for (size_type i = 0; i < ndof; ++i, ++it) {
+ // 		      size_type jj = j + tdim*l;
+ // 		      if (p == jj) output(i*qmult+l, p) += val[0]*(*it)*n[k];
+ // 		    }
+ // 		GMM_ASSERT1(it ==  t.end(), "Internal error");
+ // 	      }
+ // 	    }
+ 	    if (Q == 1) {
+ 		base_tensor::const_iterator it = t.begin();
+ 		for (size_type k = 0; k < N; ++k)
+ 		  for (size_type i = 0; i < ndof; ++i, ++it)
+ 		    output[i] += val[0]*(*it)*n[k];
+ 		GMM_ASSERT1(it ==  t.end(), "Internal error");
+ 	    } else {
+ 	      for (size_type l = 0; l < qmult; ++l) {
+ 		base_tensor::const_iterator it = t.begin();
+ 		for (size_type k = 0; k < N; ++k)
+ 		  for (size_type j = 0; j < tdim; ++j)
+ 		    for (size_type i = 0; i < ndof; ++i, ++it) {
+ 		      size_type jj = j + tdim*l;
+ 		      output(i*qmult+l, jj) += val[0]*(*it)*n[k];
+ 		    }
+ 		GMM_ASSERT1(it ==  t.end(), "Internal error");
+ 	      }
+ 	    }
+ 	  } else if (s == N*N) {
+ 	    if (Q == 1) {
+ 	      base_tensor::const_iterator it = t.begin();
+ 	      for (size_type k = 0; k < N; ++k)
+ 		for (size_type i = 0; i < ndof; ++i, ++it) {
+ 		  for (size_type q = 0; q < N; ++q)
+ 		    output[i] += val[q+k*N]*(*it)*n[q];
+ 		}
+ 	      GMM_ASSERT1(it ==  t.end(), "Internal error");
+ 	    } else {
+ 	      for (size_type l = 0; l < qmult; ++l) {
+ 		base_tensor::const_iterator it = t.begin();
+ 		for (size_type k = 0; k < N; ++k)
+ 		  for (size_type j = 0; j < tdim; ++j)
+ 		    for (size_type i = 0; i < ndof; ++i, ++it) {
+ 		      size_type jj = j + tdim*l;
+ 		      for (size_type q = 0; q < N; ++q)
+ 			output(i*qmult+l, jj) += val[q+k*N]*(*it)*n[q];
+ 		    }
+ 		GMM_ASSERT1(it ==  t.end(), "Internal error");
+ 	      } 
+ 	    }
+ 	  } else if (s == N*N*Q*Q) {
+ 	    for (size_type l = 0; l < qmult; ++l) {
+ 	      for (size_type p = 0; p < Q; ++p) {
+ 		base_tensor::const_iterator it = t.begin();
+ 		for (size_type k = 0; k < N; ++k)
+ 		  for (size_type j = 0; j < tdim; ++j)
+ 		    for (size_type i = 0; i < ndof; ++i, ++it) {
+ 		      size_type jj = j + tdim*l; 
+ 		      for (size_type q = 0; q < N; ++q)
+ 			output(i*qmult+l, p)
+ 			  += val[p+q*Q+jj*N*Q+k*N*Q*Q]*(*it)*n[q];
+ 		    }
+ 		GMM_ASSERT1(it ==  t.end(), "Internal error");
+ 	      }
+ 	    }
+ 	  } 
+ 	}
+ 	break;
+       }
+     }
+ 
+     generic_elliptic_Neumann_elem_term
+     (const mesh_fem *mf_a_, const model_real_plain_vector *A_)
+       : mf_a(mf_a_), A(A_) {}
+ 
+   };
+ 
+ 
+ 
+ 
    struct generic_elliptic_brick : public virtual_brick {
  
++<<<<<<< HEAD
 +    virtual void asm_real_tangent_terms(const model &md, size_type,
++=======
+     virtual void asm_real_tangent_terms(const model &md, size_type ib,
++>>>>>>> upstream
                                          const model::varnamelist &vl,
                                          const model::varnamelist &dl,
                                          const model::mimlist &mims,
@@@ -1339,8 -2087,10 +2385,15 @@@
            asm_stiffness_matrix_for_homogeneous_vector_elliptic
              (matl[0], mim, mf_u, *A, rg);
        } else
++<<<<<<< HEAD
 +        GMM_ASSERT1(false,
 +                    "Bad format generic elliptic brick coefficient");
++=======
+         GMM_ASSERT1(false, "Bad format generic elliptic brick coefficient");
+ 
+       pNeumann_elem_term pNt = new generic_elliptic_Neumann_elem_term(mf_a, A);
+       md.add_Neumann_term(pNt, vl[0], ib);
++>>>>>>> upstream
      }
  
      virtual scalar_type asm_real_pseudo_potential(const model &md, size_type,
@@@ -1595,7 -2345,8 +2648,12 @@@
      source_term_brick(void) {
        set_flags("Source term", true /* is linear*/,
                  true /* is symmetric */, true /* is coercive */,
++<<<<<<< HEAD
 +                true /* is real */, true /* is complex */);
++=======
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
++>>>>>>> upstream
      }
  
  
@@@ -1695,7 -2446,7 +2753,22 @@@
          asm_normal_source_term(vecl[0], mim, mf_u, *mf_data, A, rg);
        else
          asm_homogeneous_normal_source_term(vecl[0], mim, mf_u, A, rg);
++<<<<<<< HEAD
++
++    }
++=======
++>>>>>>> upstream
  
++    virtual scalar_type asm_real_pseudo_potential(const model &md, size_type,
++                                                  const model::varnamelist &vl,
++                                                  const model::varnamelist &,
++                                                  const model::mimlist &,
++                                                  model::real_matlist &,
++                                                  model::real_veclist &vecl,
++                                                  model::real_veclist &,
++                                                  size_type) const {
++      const model_real_plain_vector &u = md.real_variable(vl[0]);
++      return -gmm::vect_sp(vecl[0], u);
      }
  
      virtual scalar_type asm_real_pseudo_potential(const model &md, size_type,
@@@ -1713,7 -2464,8 +2786,12 @@@
      normal_source_term_brick(void) {
        set_flags("Normal source term", true /* is linear*/,
                  true /* is symmetric */, true /* is coercive */,
++<<<<<<< HEAD
 +                true /* is real */, true /* is complex */);
++=======
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
++>>>>>>> upstream
      }
  
  
@@@ -1745,10 -2497,10 +2823,17 @@@
      bool H_version; // The version hu = r for vector fields.
      bool normal_component; // Dirichlet on normal component for vector field.
      const mesh_fem *mf_mult_;
++<<<<<<< HEAD
 +    mutable model_real_sparse_matrix rB;
 +    mutable model_real_plain_vector rV;
 +    mutable model_complex_sparse_matrix cB;
 +    mutable model_complex_plain_vector cV;
++=======
+     mutable getfem::omp_distribute<model_real_sparse_matrix> rB_th;
+     mutable getfem::omp_distribute<model_real_plain_vector> rV_th;
+     mutable getfem::omp_distribute<model_complex_sparse_matrix> cB_th;
+     mutable getfem::omp_distribute<model_complex_plain_vector> cV_th;
++>>>>>>> upstream
  
      virtual void asm_real_tangent_terms(const model &md, size_type ib,
                                          const model::varnamelist &vl,
@@@ -1765,6 -2517,9 +2850,12 @@@
                    "Dirichlet condition brick need one and only one mesh_im");
        GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 3,
                    "Wrong number of variables for Dirichlet condition brick");
++<<<<<<< HEAD
++=======
+ 
+       model_real_sparse_matrix& rB = rB_th;
+       model_real_plain_vector&  rV = rV_th;
++>>>>>>> upstream
  
        bool penalized = (vl.size() == 1);
        const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
@@@ -1788,11 -2543,10 +2879,18 @@@
          mf_data = md.pmesh_fem_of_variable(dl[ind]);
          s = gmm::vect_size(*A);
          if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
++<<<<<<< HEAD
 +        GMM_ASSERT1(mf_u.get_qdim() ==
 +                    s * ((normal_component) ? mf_u.linked_mesh().dim() : 1),
 +                    dl[ind] << ": bad format of Dirichlet data. "
 +                    "Detected dimension is " << s << " should be "
 +                    << size_type(mf_u.get_qdim()));
++=======
+         size_type ss = ((normal_component) ? 1 :  mf_u.get_qdim());
+         GMM_ASSERT1(s == ss, dl[ind] << ": bad format of "
+ 		    "Dirichlet data. Detected dimension is " << s
+ 		    << " should be " << ss);
++>>>>>>> upstream
        }
  
        if (dl.size() > ind + 1) {
@@@ -1807,7 -2561,7 +2905,11 @@@
                    "a scalar finite element method");
      }
          GMM_ASSERT1(s = gmm::sqr(mf_u.get_qdim()),
++<<<<<<< HEAD
 +                    dl[ind] << ": bad format of Dirichlet data. "
++=======
+                     dl[ind+1] << ": bad format of Dirichlet data. "
++>>>>>>> upstream
                      "Detected dimension is " << s << " should be "
                      << size_type(gmm::sqr(mf_u.get_qdim())));
        }
@@@ -1852,9 -2606,9 +2954,15 @@@
            assem.push_mf(mf_u);
            assem.push_mf(mf_mult);
            assem.push_mat(*B);
++<<<<<<< HEAD
 +          assem.assembly(region);
 +        } else {
 +          asm_mass_matrix(*B, mim, mf_mult, mf_u, region);
++=======
+           assem.assembly(rg);
+         } else {
+           asm_mass_matrix(*B, mim, mf_mult, mf_u, rg);
++>>>>>>> upstream
          }
  
          if (penalized && (&mf_mult != &mf_u)) {
@@@ -1907,6 -2661,9 +3015,12 @@@
                    "Dirichlet condition brick need one and only one mesh_im");
        GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 3,
                    "Wrong number of variables for Dirichlet condition brick");
++<<<<<<< HEAD
++=======
+ 
+       model_complex_sparse_matrix& cB = cB_th;
+       model_complex_plain_vector&  cV = cV_th;
++>>>>>>> upstream
  
        bool penalized = (vl.size() == 1);
        const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
@@@ -1930,10 -2687,10 +3044,17 @@@
          mf_data = md.pmesh_fem_of_variable(dl[ind]);
          s = gmm::vect_size(*A);
          if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
++<<<<<<< HEAD
 +        GMM_ASSERT1(mf_u.get_qdim() ==
 +                    s * ((normal_component) ? mf_u.linked_mesh().dim() : 1),
 +                    dl[ind] << ": bad format of Dirichlet data. "
 +                    "Detected dimension is " << s << " should be "
++=======
+ 	size_type ss = s * ((normal_component) ? mf_u.linked_mesh().dim() : 1);
+         GMM_ASSERT1(mf_u.get_qdim() == ss,
+                     dl[ind] << ": bad format of Dirichlet data. "
+                     "Detected dimension is " << ss << " should be "
++>>>>>>> upstream
                      << size_type(mf_u.get_qdim()));
        }
  
@@@ -1949,7 -2706,7 +3070,11 @@@
                      "a scalar finite element method");
    }
          GMM_ASSERT1(s = gmm::sqr(mf_u.get_qdim()),
++<<<<<<< HEAD
 +                    dl[ind] << ": bad format of Dirichlet data. "
++=======
+                     dl[ind+1] << ": bad format of Dirichlet data. "
++>>>>>>> upstream
                      "Detected dimension is " << s << " should be "
                      << size_type(gmm::sqr(mf_u.get_qdim())));
        }
@@@ -1993,9 -2750,9 +3118,15 @@@
            assem.push_mf(mf_u);
            assem.push_mf(mf_mult);
            assem.push_mat(gmm::real_part(*B));
++<<<<<<< HEAD
 +          assem.assembly(region);
 +        } else {
 +          asm_mass_matrix(*B, mim, mf_mult, mf_u, region);
++=======
+           assem.assembly(rg);
+         } else {
+           asm_mass_matrix(*B, mim, mf_mult, mf_u, rg);
++>>>>>>> upstream
          }
          if (penalized && (&mf_mult != &mf_u)) {
            gmm::mult(gmm::transposed(cB), cB, matl[0]);
@@@ -2042,7 -2799,8 +3173,12 @@@
                            : "Dirichlet with multipliers brick",
                  true /* is linear*/,
                  true /* is symmetric */, penalized /* is coercive */,
++<<<<<<< HEAD
 +                true /* is real */, true /* is complex */);
++=======
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
++>>>>>>> upstream
      }
    };
  
@@@ -2088,59 -2846,6 +3224,62 @@@
    size_type add_Dirichlet_condition_with_penalization
    (model &md, const mesh_im &mim, const std::string &varname,
     scalar_type penalisation_coeff, size_type region,
++<<<<<<< HEAD
 +   const std::string &dataname, const mesh_fem *mf_mult) {
 +    std::string coeffname = md.new_name("penalization_on_" + varname);
 +    md.add_fixed_size_data(coeffname, 1);
 +    if (md.is_complex())
 +      md.set_complex_variable(coeffname)[0] = penalisation_coeff;
 +    else
 +      md.set_real_variable(coeffname)[0] = penalisation_coeff;
 +    pbrick pbr = new Dirichlet_condition_brick(true, false, false, mf_mult);
 +    model::termlist tl;
 +    tl.push_back(model::term_description(varname, varname, true));
 +    model::varnamelist vl(1, varname);
 +    model::varnamelist dl(1, coeffname);
 +    if (dataname.size()) dl.push_back(dataname);
 +    return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
 +  }
 +
 +  size_type add_normal_Dirichlet_condition_with_multipliers
 +  (model &md, const mesh_im &mim, const std::string &varname,
 +   const std::string &multname, size_type region,
 +   const std::string &dataname) {
 +    pbrick pbr = new Dirichlet_condition_brick(false, false, true);
 +    model::termlist tl;
 +    tl.push_back(model::term_description(multname, varname, true));
 +    model::varnamelist vl(1, varname);
 +    vl.push_back(multname);
 +    model::varnamelist dl;
 +    if (dataname.size()) dl.push_back(dataname);
 +    return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
 +  }
 +
 +  size_type add_normal_Dirichlet_condition_with_multipliers
 +  (model &md, const mesh_im &mim, const std::string &varname,
 +   const mesh_fem &mf_mult, size_type region,
 +   const std::string &dataname) {
 +    std::string multname = md.new_name("mult_on_" + varname);
 +    md.add_multiplier(multname, mf_mult, varname);
 +    return add_normal_Dirichlet_condition_with_multipliers
 +      (md, mim, varname, multname, region, dataname);
 +  }
 +
 +  size_type add_normal_Dirichlet_condition_with_multipliers
 +  (model &md, const mesh_im &mim, const std::string &varname,
 +   dim_type degree, size_type region,
 +   const std::string &dataname) {
 +    const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
 +    const mesh_fem &mf_mult = classical_mesh_fem(mf_u.linked_mesh(),degree, 1);
 +    return add_normal_Dirichlet_condition_with_multipliers
 +      (md, mim, varname, mf_mult, region, dataname);
 +  }
 +
 +  size_type add_normal_Dirichlet_condition_with_penalization
 +  (model &md, const mesh_im &mim, const std::string &varname,
 +   scalar_type penalisation_coeff, size_type region,
++=======
++>>>>>>> upstream
     const std::string &dataname, const mesh_fem *mf_mult) {
      std::string coeffname = md.new_name("penalization_on_" + varname);
      md.add_fixed_size_data(coeffname, 1);
@@@ -2148,7 -2853,7 +3287,11 @@@
        md.set_complex_variable(coeffname)[0] = penalisation_coeff;
      else
        md.set_real_variable(coeffname)[0] = penalisation_coeff;
++<<<<<<< HEAD
 +    pbrick pbr = new Dirichlet_condition_brick(true, false, true, mf_mult);
++=======
+     pbrick pbr = new Dirichlet_condition_brick(true, false, false, mf_mult);
++>>>>>>> upstream
      model::termlist tl;
      tl.push_back(model::term_description(varname, varname, true));
      model::varnamelist vl(1, varname);
@@@ -2157,8 -2862,61 +3300,64 @@@
      return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
    }
  
- 
-   size_type add_generalized_Dirichlet_condition_with_multipliers
++<<<<<<< HEAD
++=======
+   size_type add_normal_Dirichlet_condition_with_multipliers
+   (model &md, const mesh_im &mim, const std::string &varname,
+    const std::string &multname, size_type region,
+    const std::string &dataname) {
+     pbrick pbr = new Dirichlet_condition_brick(false, false, true);
+     model::termlist tl;
+     tl.push_back(model::term_description(multname, varname, true));
+     model::varnamelist vl(1, varname);
+     vl.push_back(multname);
+     model::varnamelist dl;
+     if (dataname.size()) dl.push_back(dataname);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+   }
+ 
+   size_type add_normal_Dirichlet_condition_with_multipliers
+   (model &md, const mesh_im &mim, const std::string &varname,
+    const mesh_fem &mf_mult, size_type region,
+    const std::string &dataname) {
+     std::string multname = md.new_name("mult_on_" + varname);
+     md.add_multiplier(multname, mf_mult, varname);
+     return add_normal_Dirichlet_condition_with_multipliers
+       (md, mim, varname, multname, region, dataname);
+   }
+ 
+   size_type add_normal_Dirichlet_condition_with_multipliers
+   (model &md, const mesh_im &mim, const std::string &varname,
+    dim_type degree, size_type region,
+    const std::string &dataname) {
+     const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
+     const mesh_fem &mf_mult = classical_mesh_fem(mf_u.linked_mesh(),degree, 1);
+     return add_normal_Dirichlet_condition_with_multipliers
+       (md, mim, varname, mf_mult, region, dataname);
+   }
+ 
+   size_type add_normal_Dirichlet_condition_with_penalization
+   (model &md, const mesh_im &mim, const std::string &varname,
+    scalar_type penalisation_coeff, size_type region,
+    const std::string &dataname, const mesh_fem *mf_mult) {
+     std::string coeffname = md.new_name("penalization_on_" + varname);
+     md.add_fixed_size_data(coeffname, 1);
+     if (md.is_complex())
+       md.set_complex_variable(coeffname)[0] = penalisation_coeff;
+     else
+       md.set_real_variable(coeffname)[0] = penalisation_coeff;
+     pbrick pbr = new Dirichlet_condition_brick(true, false, true, mf_mult);
+     model::termlist tl;
+     tl.push_back(model::term_description(varname, varname, true));
+     model::varnamelist vl(1, varname);
+     model::varnamelist dl(1, coeffname);
+     if (dataname.size()) dl.push_back(dataname);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+   }
+ 
++>>>>>>> upstream
+ 
+   size_type add_generalized_Dirichlet_condition_with_multipliers
    (model &md, const mesh_im &mim, const std::string &varname,
     const std::string &multname, size_type region,
     const std::string &dataname, const std::string &Hname) {
@@@ -2207,368 -2965,1279 +3406,1565 @@@
        md.set_real_variable(coeffname)[0] = penalisation_coeff;
      pbrick pbr = new Dirichlet_condition_brick(true, true, false, mf_mult);
      model::termlist tl;
-     tl.push_back(model::term_description(varname, varname, true));
+     tl.push_back(model::term_description(varname, varname, true));
+     model::varnamelist vl(1, varname);
+     model::varnamelist dl(1, coeffname);
+     dl.push_back(dataname);
+     dl.push_back(Hname);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+   }
+ 
+   void change_penalization_coeff(model &md, size_type ind_brick,
+                                  scalar_type penalisation_coeff) {
+     const std::string &coeffname = md.dataname_of_brick(ind_brick, 0);
+     if (!md.is_complex()) {
+       model_real_plain_vector &d = md.set_real_variable(coeffname);
+       GMM_ASSERT1(gmm::vect_size(d)==1,
+                   "Wrong coefficient size, may be not a Dirichlet brick "
+                   "with penalization");
+       d[0] = penalisation_coeff;
+     }
+     else {
+       model_complex_plain_vector &d = md.set_complex_variable(coeffname);
+       GMM_ASSERT1(gmm::vect_size(d)==1,
+                   "Wrong coefficient size, may be not a Dirichlet brick "
+                   "with penalization");
+       d[0] = penalisation_coeff;
+     }
+   }
+ 
++<<<<<<< HEAD
++=======
+   // ----------------------------------------------------------------------
+   //
+   // Dirichlet condition brick with simplification
+   //
+   // ----------------------------------------------------------------------
+ 
+   struct simplification_Dirichlet_condition_brick : public virtual_brick {
+ 
+     virtual void asm_real_tangent_terms(const model &md, size_type /*ib*/,
+                                         const model::varnamelist &vl,
+                                         const model::varnamelist &dl,
+                                         const model::mimlist &mims,
+                                         model::real_matlist &matl,
+                                         model::real_veclist &vecl,
+                                         model::real_veclist &,
+                                         size_type region,
+                                         build_version /*version*/) const {
+       GMM_ASSERT1(vecl.size() == 0 && matl.size() == 0,
+                   "Dirichlet condition brick by simplification has no term");
+       GMM_ASSERT1(mims.size() == 0,
+                   "Dirichlet condition brick by simplification need no "
+                   "mesh_im");
+       GMM_ASSERT1(vl.size() == 1 && dl.size() <= 1,
+                   "Wrong number of variables for Dirichlet condition brick "
+                   "by simplification");
+ 
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+       const model_real_plain_vector *A = 0;
+       const mesh_fem *mf_data = 0;
+       size_type s = 0;
+ 
+       if (dl.size() == 1) {
+         A = &(md.real_variable(dl[0]));
+         mf_data = md.pmesh_fem_of_variable(dl[0]);
+ 
+         if (mf_data) {
+           GMM_ASSERT1(mf_data == &mf_u, "Sorry, for this brick, the data has "
+                      "to be define on the same f.e.m. than the unknown");
+         } else {
+           s = gmm::vect_size(*A);
+           GMM_ASSERT1(mf_u.get_qdim() == s, ": bad format of "
+ 		    "Dirichlet data. Detected dimension is " << s
+ 		    << " should be " << size_type(mf_u.get_qdim())); 
+         }
+       }
+ 
+       mesh_region rg(region);
+       // mf_u.linked_mesh().intersect_with_mpi_region(rg); // Not distributed
+       // for the moment. To distribute, model::assembly should gather the 
+       // dof constraints.
+ 
+       if (mf_u.get_qdim() > 1 || (!mf_data && A)) {
+         for (mr_visitor i(rg, mf_u.linked_mesh()); !i.finished(); ++i) {
+           pfem pf = mf_u.fem_of_element(i.cv());
+           if (pf) {
+             GMM_ASSERT1(pf->target_dim() == 1,
+                         "Intrinsically vectorial fems are not allowed");
+             GMM_ASSERT1(mf_data || pf->is_lagrange(),
+                    "Constant Dirichlet data allowed for lagrange fems only");
+           }
+         }
+       }
+ 
+       dal::bit_vector dofs = mf_u.dof_on_region(rg);
+ 
+       if (A && !mf_data) {
+         GMM_ASSERT1(dofs.card() % s == 0, "Problem with dof vectorization");
+       }
+ 
+       for (dal::bv_visitor i(dofs); !i.finished(); ++i) {
+         scalar_type val(0);
+         if (A) val = (mf_data ? (*A)[i] :  (*A)[i%s]);
+         md.add_real_dof_constraint(vl[0], i, val);
+       }
+     }
+ 
+     virtual void asm_complex_tangent_terms(const model &md, size_type /*ib*/,
+                                            const model::varnamelist &vl,
+                                            const model::varnamelist &dl,
+                                            const model::mimlist &mims,
+                                            model::complex_matlist &matl,
+                                            model::complex_veclist &vecl,
+                                            model::complex_veclist &,
+                                            size_type region,
+                                            build_version /*version*/) const {
+       GMM_ASSERT1(vecl.size() == 0 && matl.size() == 0,
+                   "Dirichlet condition brick by simplification has no term");
+       GMM_ASSERT1(mims.size() == 0,
+                   "Dirichlet condition brick by simplification need no "
+                   "mesh_im");
+       GMM_ASSERT1(vl.size() == 1 && dl.size() <= 1,
+                   "Wrong number of variables for Dirichlet condition brick "
+                   "by simplification");
+ 
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+       const model_complex_plain_vector *A = 0;
+       const mesh_fem *mf_data = 0;
+       size_type s = 0;
+        
+       if (dl.size() == 1) {
+         A = &(md.complex_variable(dl[0]));
+         mf_data = md.pmesh_fem_of_variable(dl[0]);
+ 
+         if (mf_data) {
+           GMM_ASSERT1(mf_data == &mf_u, "Sorry, for this brick, the data has "
+                      "to be define on the same f.e.m. than the unknown");
+         } else {
+           s = gmm::vect_size(*A);
+           GMM_ASSERT1(mf_u.get_qdim() == s, ": bad format of "
+ 		    "Dirichlet data. Detected dimension is " << s
+ 		    << " should be " << size_type(mf_u.get_qdim())); 
+         }
+       }
+ 
+       mesh_region rg(region);
+       // mf_u.linked_mesh().intersect_with_mpi_region(rg); // Not distributed
+       // for the moment. To distribute, model::assembly should gather the 
+       // dof constraints.
+ 
+       if (mf_u.get_qdim() > 1 || (!mf_data && A)) {
+         for (mr_visitor i(rg, mf_u.linked_mesh()); !i.finished(); ++i) {
+           pfem pf = mf_u.fem_of_element(i.cv());
+           if (pf) {
+             GMM_ASSERT1(pf->target_dim() == 1,
+                         "Intrinsically vectorial fems are not allowed");
+             GMM_ASSERT1(mf_data || pf->is_lagrange(),
+                    "Constant Dirichlet data allowed for lagrange fems only");
+           }
+         }
+       }
+ 
+       dal::bit_vector dofs = mf_u.dof_on_region(rg);
+ 
+       if (A && !mf_data) {
+         GMM_ASSERT1(dofs.card() % s == 0, "Problem with dof vectorization");
+       }
+ 
+       for (dal::bv_visitor i(dofs); !i.finished(); ++i) {
+         complex_type val(0);
+         if (A) val = (mf_data ? (*A)[i] :  (*A)[i%s]);
+         md.add_complex_dof_constraint(vl[0], i, val);
+       }
+     }
+ 
+     simplification_Dirichlet_condition_brick(void) {
+       set_flags("Dirichlet with simplification brick",
+                 true /* is linear*/,
+                 true /* is symmetric */, true /* is coercive */,
+                 true /* is real */, true /* is complex */,
+ 		true /* compute each time */, false /* has a Neumann term */);
+     }
+   };
+ 
+   size_type add_Dirichlet_condition_with_simplification
+   (model &md, const std::string &varname,
+    size_type region, const std::string &dataname) {
+     pbrick pbr = new simplification_Dirichlet_condition_brick();
+     model::termlist tl;
+     model::varnamelist vl(1, varname);
+     model::varnamelist dl;
+     if (dataname.size()) dl.push_back(dataname);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(), region);
+   }
+ 
+   // ----------------------------------------------------------------------
+   //
+   // Dirichlet condition brick with Nitsche's method 
+   //
+   // ----------------------------------------------------------------------
+ 
+   struct dirichlet_nitsche_nonlinear_term : public nonlinear_elem_term {
+     // Option:
+     // 1 : matrix term H^TH/gamma
+     // 2 : matrix term -(D_u G(u,lambda)[w])^TH^TH
+     // 3 : matrix term theta(g-Hu)^TH(D^2_uu G(u,lambda)[w,v])
+     // 4 : rhs term (H^Tg)/gamma
+     // 5 : rhs term H^T((g-Hu)/gamma + HG(u,lambda))
+     // 6 : rhs term -theta(g)^TH(D_uG(u, lambda)[v])
+     // 7 : rhs term theta(Hu-g)^TH(DG(u, lambda)[v])
+     // 8 : matrix term theta(g-Hu)^TH(D^2_{u,lambda}G(u, lambda)[w,v])
+     // 9 : matrix term -(D_lambda G(u,lambda)[w])^TH^TH
+ 
+     dim_type N, qdim;
+     size_type option;
+     const model *md;
+     const std::string *varname, *auxvarname;
+     bool H_version, normal_component;
+     scalar_type theta, gamma0;
+ 
+ 
+     base_small_vector auxg, auxn, u, g, n;
+     base_tensor tp;
+     scalar_type gamma;
+     base_vector coeff;
+     base_matrix H, HTH, auxH;
+     const mesh_fem *mf_u, *mf_lambda;    
+     const mesh_fem *mf_data;
+     const mesh_fem *mf_H;
+     
+     base_vector U;
+     const base_vector &HH, &G;
+ 
+     mutable bgeot::multi_index sizes_;
+ 
+ 
+     void adjust_tensor_size(void) {
+       switch(option) {
+       case 1:
+ 	if (qdim > 1) { sizes_.resize(2); sizes_[0] = sizes_[1] = qdim; }
+ 	else { sizes_.resize(1); sizes_[0] = 1; }
+ 	break;
+       case 2: case 9:
+ 	if (qdim > 1)
+ 	  { sizes_.resize(2); sizes_[0] = 0; sizes_[1] = qdim; }
+ 	else { sizes_.resize(1); sizes_[0] = 0; }
+ 	break;
+       case 3: case 8:
+ 	sizes_.resize(3);
+ 	sizes_[0] = sizes_[1] = 0; sizes_[2] = 1;
+ 	break;
+       case 4: case 5:
+ 	sizes_.resize(1); sizes_[0] = qdim;
+ 	break;
+       case 6: case 7:
+ 	sizes_.resize(2); sizes_[0] = 0; sizes_[1] = 1;
+ 	break;
+       }
+ 
+       gmm::resize(u, qdim);
+       gmm::resize(auxg, 1);
+       gmm::resize(auxn, qdim);
+       gmm::resize(g, normal_component ? 1 : qdim); 
+       gmm::resize(H, qdim, qdim); gmm::resize(HTH, qdim, qdim);
+       gmm::resize(auxH, qdim, 1);
+     }
+     
+     const bgeot::multi_index &sizes(size_type cv) const {
+       if (cv != size_type(-1))
+ 	switch(option) {
+ 	case 2:
+ 	  sizes_[0] = short_type(mf_u->nb_basic_dof_of_element(cv));
+ 	  break;
+ 	case 9:
+ 	  sizes_[0] = short_type(mf_lambda->nb_basic_dof_of_element(cv));
+ 	  break;
+ 	case 3:
+ 	  sizes_[0] = sizes_[1] = short_type(mf_u->nb_basic_dof_of_element(cv));
+ 	  break;
+ 	case 8:
+ 	  sizes_[0] = short_type(mf_u->nb_basic_dof_of_element(cv));
+ 	  sizes_[1] = short_type(mf_lambda->nb_basic_dof_of_element(cv));
+ 	  break;
+ 	case 6: case 7:
+ 	  sizes_[0] = short_type(mf_u->nb_basic_dof_of_element(cv));
+ 	  break;
+ 	}
+       return sizes_;
+     }
+ 
+     dirichlet_nitsche_nonlinear_term
+     (size_type option_, const model *md_, const std::string *varname_,
+      const mesh_fem *mfu_, const model_real_plain_vector *U_,
+      scalar_type theta_, scalar_type gamma0_, bool H_version_,
+      bool normal_component_, const mesh_fem *mf_data_ = 0,
+      const model_real_plain_vector *G_ = 0, const mesh_fem *mf_H_ = 0,
+      const model_real_plain_vector *H_ = 0,
+      const std::string *auxvarname_ = 0, const mesh_fem *mf_lambda_ = 0
+      )
+       : option(option_), md(md_), varname(varname_), auxvarname(auxvarname_),
+ 	H_version(H_version_), normal_component(normal_component_),
+ 	theta(theta_), gamma0(gamma0_), mf_u(mfu_), mf_lambda(mf_lambda_),
+ 	mf_data(mf_data_), mf_H(mf_H_), HH(*H_), G(*G_) {
+ 
+       N = mf_u->linked_mesh().dim();
+       qdim = mf_u->get_qdim();
+       adjust_tensor_size();
+ 
+       if (U_) {
+ 	gmm::resize(U, mf_u->nb_basic_dof());
+ 	mf_u->extend_vector(*U_, U);
+       }
+ 
+       if (mf_data) GMM_ASSERT1(!(mf_data->is_reduced()),
+ 			       "Reduced fem not allowed for data");
+       if (mf_H) GMM_ASSERT1(!(mf_H->is_reduced()),
+ 			    "Reduced fem not allowed for data");
+     }
+     
+     void compute(fem_interpolation_context &ctx, bgeot::base_tensor &t) {
+       
+       dim_type i;
+       // size_type cv = ctx.convex_num();
+       
+       switch (option) {
+       case 1:
+ 	for (i = 0; i < qdim*qdim; ++i) t[i] = HTH[i]/gamma;
+ 	break;
+       case 2:
+ 	if (qdim == 1) {
+ 	  md->compute_Neumann_terms(2, *varname, *mf_u, U, ctx, n, t);
+ 	  t *= -scalar_type(1);
+ 	} else {
+ 	  tp.adjust_sizes(sizes_);
+ 	  md->compute_Neumann_terms(2, *varname, *mf_u, U, ctx, n, tp);
+ 	  t.mat_reduction(tp, HTH, 1);
+ 	  t *= -scalar_type(1);
+ 	}
+ 	break;
+       case 9:
+ 	if (qdim == 1) {
+ 	  md->compute_auxilliary_Neumann_terms(2, *varname, *mf_u, U,
+ 					       *auxvarname, ctx, n, t);
+ 	  t *= -scalar_type(1);
+ 	} else {
+ 	  tp.adjust_sizes(sizes_);
+ 	  md->compute_auxilliary_Neumann_terms(2, *varname, *mf_u, U,
+ 					       *auxvarname,ctx, n, tp);
+ 	  t.mat_reduction(tp, HTH, 1);
+ 	  t *= -scalar_type(1);
+ 	}
+ 	break;
+       case 3:
+ 	sizes_[2] = qdim;
+ 	tp.adjust_sizes(sizes_);
+ 	sizes_[2] = 1;
+ 	md->compute_Neumann_terms(3, *varname, *mf_u, U, ctx, n, tp);
+ 	gmm::mult(H, gmm::scaled(u, -theta), gmm::scaled(g, theta), auxn);
+ 	gmm::mult(gmm::transposed(H), gmm::col_vector(auxn), auxH);
+ 	t.mat_reduction(tp, auxH, 2);
+ 	break;
+       case 8:
+ 	sizes_[2] = qdim;
+ 	tp.adjust_sizes(sizes_);
+ 	sizes_[2] = 1;
+ 	md->compute_auxilliary_Neumann_terms(3, *varname,  *mf_u, U,
+ 					     *auxvarname, ctx, n, tp);
+ 	gmm::mult(H, gmm::scaled(u, -theta), gmm::scaled(g, theta), auxn);
+ 	gmm::mult(gmm::transposed(H), gmm::col_vector(auxn), auxH);
+ 	t.mat_reduction(tp, auxH, 2);
+ 	break;
+       case 4:
+ 	gmm::mult(gmm::transposed(H), g, t.as_vector());
+ 	t /= gamma;
+ 	break;	
+       case 5:
+         gmm::mult(H, gmm::scaled(u, -scalar_type(1)), g, auxn);
+         gmm::scale(auxn, scalar_type(1)/gamma);
+ 	tp.adjust_sizes(sizes_);
+ 	md->compute_Neumann_terms(1, *varname, *mf_u, U, ctx, n, tp);
+ 	gmm::mult_add(H, tp.as_vector(), auxn); 
+ 	gmm::mult(gmm::transposed(H), auxn, t.as_vector());
+ 	break;
+       case 6:
+ 	sizes_[1] = qdim;
+ 	tp.adjust_sizes(sizes_);
+ 	sizes_[1] = 1;
+ 	md->compute_Neumann_terms(2, *varname, *mf_u, U, ctx, n, tp);
+ 	gmm::copy(gmm::scaled(g, -theta), auxn);
+ 	gmm::mult(gmm::transposed(H), gmm::col_vector(auxn), auxH);
+ 	t.mat_reduction(tp, auxH, 1);
+ 	break;
+       case 7:
+ 	sizes_[1] = qdim;
+ 	tp.adjust_sizes(sizes_);
+ 	sizes_[1] = 1;
+ 	md->compute_Neumann_terms(2, *varname, *mf_u, U, ctx, n, tp);
+ 	gmm::mult(H, gmm::scaled(u, theta), gmm::scaled(g, -theta), auxn);
+ 	gmm::mult(gmm::transposed(H), gmm::col_vector(auxn), auxH);
+ 	t.mat_reduction(tp, auxH, 1);
+ 	break;
+       }
+     }
+ 
+     void prepare(fem_interpolation_context& ctx, size_type nb) {
+       size_type cv = ctx.convex_num();
+ 
+       switch (nb) { // last is computed first
+       case 1 : // mandatory. calculate [u], [n], [gamma], [HTH]
+ 	n = bgeot::compute_normal(ctx, ctx.face_num());
+ 	n /= gmm::vect_norm2(n);
+ 	if (mf_u && gmm::vect_size(U)) {
+ 	  coeff.resize(mf_u->nb_basic_dof_of_element(cv));
+ 	  gmm::copy(gmm::sub_vector(U, gmm::sub_index
+ 			       (mf_u->ind_basic_dof_of_element(cv))), coeff);
+ 	  ctx.pf()->interpolation(ctx, coeff, u, qdim);
+ 	}
+ 	if (normal_component) {
+ 	  GMM_ASSERT1(qdim == N, "dimensions mismatch");
+ 	  for (size_type i = 0; i < qdim; ++i)
+ 	    for (size_type j = 0; j < qdim; ++j)
+ 	      HTH(i,j) = H(i,j) = n[i]*n[j];
+ 	}
+ 	else if (!H_version) {
+ 	  gmm::copy(gmm::identity_matrix(), HTH);
+ 	  gmm::copy(gmm::identity_matrix(), H);
+ 	}
+ 	else {
+ 	  GMM_ASSERT1(&HH && gmm::vect_size(HH), "Need H in this case !");
+ 	  if (!mf_H) gmm::copy(HH, H.as_vector());
+ 	  gmm::clear(HTH);
+ 	  for (size_type i = 0; i < qdim; ++i)
+ 	    for (size_type j = 0; j < qdim; ++j)
+ 	      for (size_type k = 0; k < qdim; ++k)
+ 		HTH(i,j) += H(k,i) * H(k,j);
+ 	}
+ 	if (!mf_data) {
+ 	  if (&G && gmm::vect_size(G))
+ 	    if (normal_component) gmm::copy(G, auxg); else gmm::copy(G, g);
+ 	  else
+ 	    if (normal_component) gmm::clear(auxg); else gmm::clear(g);
+ 	}
+ 	if (normal_component) gmm::copy(gmm::scaled(n, auxg[0]), g);
+ 	// computation of h for gamma = gamma0*h
+ 	scalar_type emax, emin; gmm::condition_number(ctx.K(),emax,emin);
+ 	gamma = gamma0 * emax / sqrt(scalar_type(N));
+ 	break;
+ 	
+       case 2 : // calculate [g]
+ 	if (&G && gmm::vect_size(G)) {
+ 	  size_type ndof = mf_data->nb_basic_dof_of_element(cv);
+ 	  size_type qmult = qdim / mf_data->get_qdim();
+ 	  coeff.resize(ndof * qmult);
+ 	  mesh_fem::ind_dof_ct ct = mf_data->ind_basic_dof_of_element(cv);
+ 	  for (size_type i = 0; i < ndof; ++i)
+ 	    for (size_type j = 0; j < qmult; ++j)
+ 	      coeff[i*qmult+j] = G[ct[i]*qmult+j];
+ 	  if (normal_component)
+ 	    ctx.pf()->interpolation(ctx, coeff, auxg, 1);
+ 	  else
+ 	    ctx.pf()->interpolation(ctx, coeff, g, qdim);
+ 	}
+ 	break;
+ 	
+       case 3 :// calculate [H]
+ 	if (&HH && gmm::vect_size(HH)) {
+ 	  size_type ndof = mf_H->nb_basic_dof_of_element(cv);
+ 	  size_type qmult = qdim*qdim / mf_H->get_qdim();
+ 	  coeff.resize(ndof * qmult);
+ 	  mesh_fem::ind_dof_ct ct = mf_H->ind_basic_dof_of_element(cv);
+ 	  for (size_type i = 0; i < ndof; ++i)
+ 	    for (size_type j = 0; j < qmult; ++j)
+ 	      coeff[i*qmult+j] = HH[ct[i]*qmult+j];
+ 	  ctx.pf()->interpolation(ctx, coeff, H.as_vector(),
+ 				  dim_type(qdim*qdim));
+ 	}
+ 	break;
+ 	
+       default : GMM_ASSERT1(false, "Invalid option");
+       }
+     }
+   };
+ 
+   void asm_Dirichlet_Nitsche_first_tangent_term
+   (model_real_sparse_matrix &M, const mesh_im &mim, const model &md,
+    const std::string &varname, const mesh_fem &mfu,
+    const model_real_plain_vector *U,
+    scalar_type theta, scalar_type gamma0, bool H_version,
+    bool normal_component, const mesh_fem *mf_H,
+    const model_real_plain_vector *H, const mesh_region &rg) {
+     
+     dirichlet_nitsche_nonlinear_term nterm(2, &md, &varname, &mfu, U, theta,
+ 					   gamma0, H_version, normal_component,
+ 					   0, 0, mf_H, H);
+ 
+     getfem::generic_assembly assem;
+     
+     std::string Nlinfems = mf_H ? "#1,#1,#2" : "#1";
+     
+     if (mfu.get_qdim() > 1)
+       assem.set("M(#1,#1)+=comp(vBase(#1).NonLin$1(#1,"+Nlinfems+"))(:,i,:,i);");
+     else
+       assem.set("M(#1,#1)+=comp(Base(#1).NonLin$1(#1,#1))(:,:);");
+     assem.push_mi(mim);
+     assem.push_mf(mfu);
+     if (mf_H) assem.push_mf(*mf_H);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_mat(M);
+     assem.assembly(rg);
+   }
+ 
+   void asm_Dirichlet_Nitsche_second_tangent_term
+   (model_real_sparse_matrix &M, const mesh_im &mim, const mesh_fem &mfu,
+    scalar_type theta, scalar_type gamma0, bool H_version,
+    bool normal_component, const mesh_fem *mf_H,
+    const model_real_plain_vector *H, const mesh_region &rg) {
+     
+     
+     dirichlet_nitsche_nonlinear_term nterm(1, 0, 0, &mfu, 0, theta, gamma0, 
+ 					   H_version, normal_component,
+ 					   0, 0, mf_H, H);
+     
+     getfem::generic_assembly assem;
+     
+     std::string Nlinfems = mf_H ? "#1,#1,#2" : "#1";
+     
+     if (mfu.get_qdim() > 1)
+       assem.set("M(#1,#1)+=sym(comp(NonLin$1(#1,"+Nlinfems+").vBase(#1).vBase(#1))(i,j,:,i,:,j));");
+     else
+       assem.set("M(#1,#1)+=sym(comp(NonLin$1(#1,#1).Base(#1).Base(#1))(i,:,:));");
+     assem.push_mi(mim);
+     assem.push_mf(mfu);
+     if (mf_H) assem.push_mf(*mf_H);
+     assem.push_nonlinear_term(&nterm);
+   
+     assem.push_mat(M);
+     assem.assembly(rg);
+   }
+ 
+ 
+   void asm_Dirichlet_Nitsche_third_tangent_term
+   (model_real_sparse_matrix &M, const mesh_im &mim, const model &md,
+    const std::string &varname, const mesh_fem &mfu,
+    const model_real_plain_vector *U, scalar_type theta, scalar_type gamma0,
+    bool H_version, bool normal_component,
+    const mesh_fem *mf_H, const model_real_plain_vector *H,
+    const mesh_fem *mf_data, const model_real_plain_vector *G,
+    const mesh_region &rg) {
+     
+     dirichlet_nitsche_nonlinear_term nterm(3, &md, &varname, &mfu, U, theta,
+ 					   gamma0, H_version, normal_component,
+ 					   mf_data, G, mf_H, H);
+     
+     getfem::generic_assembly assem;
+ 
+     std::string Nlinfems = "#1";
+     if (mf_H && mf_data) Nlinfems = "#1,#2,#3";
+     else if (mf_H) Nlinfems = "#1,#1,#2";
+     else if (mf_data) Nlinfems = "#1,#2";
+     
+     assem.set("M(#1,#1)+=comp(NonLin$1(#1,"+Nlinfems+"))(:,:,i);");
+     assem.push_mi(mim);
+     assem.push_mf(mfu);
+     if (mf_data) assem.push_mf(*mf_data);
+     if (mf_H) assem.push_mf(*mf_H);
+     assem.push_nonlinear_term(&nterm);
+   
+     assem.push_mat(M);
+     assem.assembly(rg);
+   }
+ 
+ 
+   void asm_Dirichlet_Nitsche_fourth_tangent_term
+   (model_real_sparse_matrix &M, const mesh_im &mim, const model &md,
+    const std::string &varname, const mesh_fem &mfu,
+    const model_real_plain_vector *U,
+    const std::string &auxvarname, const mesh_fem &mf_lambda,
+    scalar_type theta,
+    scalar_type gamma0, bool H_version, bool normal_component,
+    const mesh_fem *mf_H, const model_real_plain_vector *H,
+    const mesh_fem *mf_data, const model_real_plain_vector *G,
+    const mesh_region &rg) {
+     
+     dirichlet_nitsche_nonlinear_term nterm(8, &md, &varname, &mfu, U, theta,
+ 					   gamma0, H_version, normal_component,
+ 					   mf_data, G, mf_H, H, &auxvarname,
+ 					   &mf_lambda);
+     getfem::generic_assembly assem;
+ 
+     std::string Nlinfems = "#1", lambdafem = "#2";
+     if (mf_H && mf_data) { Nlinfems = "#1,#2,#3"; lambdafem = "#4"; }
+     else if (mf_H) { Nlinfems = "#1,#1,#2"; lambdafem = "#3"; }
+     else if (mf_data) { Nlinfems = "#1,#2"; lambdafem = "#3"; }
+     
+     assem.set("M(#1,"+lambdafem+")+=comp(NonLin$1(#1,"+Nlinfems+"))(:,:,i);");
+     assem.push_mi(mim);
+     assem.push_mf(mfu);
+     if (mf_data) assem.push_mf(*mf_data);
+     if (mf_H) assem.push_mf(*mf_H);
+     assem.push_mf(mf_lambda);
+     assem.push_nonlinear_term(&nterm);
+   
+     assem.push_mat(M);
+     assem.assembly(rg);
+   }
+ 
+   void asm_Dirichlet_Nitsche_fifth_tangent_term
+   (model_real_sparse_matrix &M, const mesh_im &mim, const model &md,
+    const std::string &varname, const mesh_fem &mfu,
+    const model_real_plain_vector *U,
+    const std::string &auxvarname, const mesh_fem &mf_lambda,
+    scalar_type theta, scalar_type gamma0, bool H_version,
+    bool normal_component, const mesh_fem *mf_H,
+    const model_real_plain_vector *H, const mesh_region &rg) {
+ 
+     dirichlet_nitsche_nonlinear_term nterm(9, &md, &varname, &mfu, U, theta,
+ 					   gamma0, H_version, normal_component,
+ 					   0, 0, mf_H, H, &auxvarname,
+ 					   &mf_lambda);
+     getfem::generic_assembly assem;
+     
+     std::string Nlinfems = mf_H ? "#1,#1,#2" : "#1";
+     std::string lambdafem = mf_H ? "#3" : "#2";
+     
+     if (mfu.get_qdim() > 1)
+       assem.set("M(#1,"+lambdafem+")+=comp(vBase(#1).NonLin$1(#1,"+Nlinfems+"))(:,i,:,i);");
+     else
+       assem.set("M(#1,"+lambdafem+")+=comp(Base(#1).NonLin$1(#1,#1))(:,:);");
+     assem.push_mi(mim);
+     assem.push_mf(mfu);
+     if (mf_H) assem.push_mf(*mf_H);
+     assem.push_mf(mf_lambda);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_mat(M);
+     assem.assembly(rg);
+   }
+ 
+ 
+   void asm_Dirichlet_Nitsche_first_rhs_term
+   (model_real_plain_vector &V, const mesh_im &mim, const model &md,
+    const std::string &varname, const mesh_fem &mfu,
+    const model_real_plain_vector *U, scalar_type theta, scalar_type gamma0,
+    bool H_version, bool normal_component,
+    const mesh_fem *mf_H, const model_real_plain_vector *H,
+    const mesh_fem *mf_data, const model_real_plain_vector *G, bool is_linear,
+    const mesh_region &rg) {
+     
+     dirichlet_nitsche_nonlinear_term nterm(is_linear ? 4:5, &md, &varname,
+ 					   &mfu, U, theta, gamma0, H_version,
+ 					   normal_component, mf_data,
+ 					   G, mf_H, H);
+     
+     getfem::generic_assembly assem;
+     std::string Nlinfems = "#1";
+     if (mf_H && mf_data) Nlinfems = "#1,#2,#3";
+     else if (mf_H) Nlinfems = "#1,#1,#2";
+     else if (mf_data) Nlinfems = "#1,#2";
+     
+     if (mfu.get_qdim() > 1)
+       assem.set("V(#1)+=comp(NonLin$1(#1,"+Nlinfems+").vBase(#1))(i,:,i);");
+     else
+       assem.set("V(#1)+=comp(NonLin$1(#1,"+Nlinfems+").Base(#1))(i,:);");
+     assem.push_mi(mim);
+     assem.push_mf(mfu);
+     if (mf_data) assem.push_mf(*mf_data);
+     if (mf_H) assem.push_mf(*mf_H);
+     assem.push_nonlinear_term(&nterm);
+   
+     assem.push_vec(V);
+     assem.assembly(rg);
+   }
+ 
+   void asm_Dirichlet_Nitsche_second_rhs_term
+   (model_real_plain_vector &V, const mesh_im &mim, const model &md,
+    const std::string &varname, const mesh_fem &mfu,
+    const model_real_plain_vector *U, scalar_type theta, scalar_type gamma0,
+    bool H_version, bool normal_component,
+    const mesh_fem *mf_H, const model_real_plain_vector *H,
+    const mesh_fem *mf_data, const model_real_plain_vector *G, bool is_linear,
+    const mesh_region &rg) {
+     
+     dirichlet_nitsche_nonlinear_term nterm(is_linear ? 6:7, &md, &varname,
+ 					   &mfu, U, theta, gamma0, H_version,
+ 					   normal_component, mf_data,
+ 					   G, mf_H, H);
+     
+     getfem::generic_assembly assem;
+ 
+     std::string Nlinfems = "#1";
+     if (mf_H && mf_data) Nlinfems = "#1,#2,#3";
+     else if (mf_H) Nlinfems = "#1,#1,#2";
+     else if (mf_data) Nlinfems = "#1,#2";
+     
+     assem.set("V(#1)+=comp(NonLin$1(#1,"+Nlinfems+"))(:,i);");
+     assem.push_mi(mim);
+     assem.push_mf(mfu);
+     if (mf_data) assem.push_mf(*mf_data);
+     if (mf_H) assem.push_mf(*mf_H);
+     assem.push_nonlinear_term(&nterm);
+   
+     assem.push_vec(V);
+     assem.assembly(rg);
+   }
+ 
+ 
+   struct Nitsche_Dirichlet_condition_brick : public virtual_brick {
+ 
+     bool H_version; // The version hu = r for vector fields.
+     bool normal_component; // Dirichlet on normal component for vector field.
+     bool linear_version;
+     scalar_type theta;
+ 
+     virtual void asm_real_tangent_terms(const model &md, size_type ib,
+                                         const model::varnamelist &vl,
+                                         const model::varnamelist &dl,
+                                         const model::mimlist &mims,
+                                         model::real_matlist &matl,
+                                         model::real_veclist &vecl,
+                                         model::real_veclist &,
+                                         size_type region,
+                                         build_version version) const {
+       GMM_ASSERT1(vecl.size() == vl.size() && matl.size() == vl.size(),
+                   "Wrong number of terms for Dirichlet condition brick");
+       GMM_ASSERT1(mims.size() == 1,
+                   "Dirichlet condition brick need one and only one mesh_im");
+       GMM_ASSERT1(vl.size() >= 1 && dl.size() >= 1 && dl.size() <= 3,
+                   "Wrong number of variables for Dirichlet condition brick");
+ 
+       
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+       const model_real_plain_vector *U = &(md.real_variable(vl[0]));
+       const mesh_im &mim = *mims[0];
+       const model_real_plain_vector *G = 0, *H = 0;
+       const mesh_fem *mf_data = 0, *mf_H = 0;
+       bool recompute_matrix = (!is_linear() && (version & model::BUILD_MATRIX))
+ 	|| (is_linear() && (!((version & model::BUILD_ON_DATA_CHANGE) != 0)
+ 			    || md.is_var_newer_than_brick(dl[0], ib)
+ 			    || md.is_var_newer_than_brick(dl[1], ib)));
+ 
+       GMM_ASSERT1(gmm::vect_size(md.real_variable(dl[0])) == 1,
+ 		  "Parameter gamma0 for Nitsche's method should be a scalar");
+       scalar_type gamma0 = md.real_variable(dl[0])[0];
+             
+       size_type s = 0, ind = 1;
+       if (dl.size() > 1 + (H_version ? 1:0)) {
+ 	++ind;
+         G = &(md.real_variable(dl[1]));
+         mf_data = md.pmesh_fem_of_variable(dl[1]);
+         s = gmm::vect_size(*G);
+         if (mf_data) s = s * mf_data->get_qdim() / mf_data->nb_dof();
+ 	size_type ss = s * ((normal_component) ? mf_u.linked_mesh().dim() : 1);
+         GMM_ASSERT1(mf_u.get_qdim() == ss, dl[1] << ": bad format of "
+ 		    "Dirichlet data. Detected dimension is " << ss
+ 		    << " should be " << size_type(mf_u.get_qdim()));
+       }
+       
+       if (H_version) {
+         GMM_ASSERT1(H_version,
+                     "Wrong number of data for Dirichlet condition brick");
+         H = &(md.real_variable(dl[ind]));
+         mf_H = md.pmesh_fem_of_variable(dl[ind]);
+         s = gmm::vect_size(*H);
+ 	if (mf_H) {
+ 	  s = s * mf_H->get_qdim() / mf_H->nb_dof();
+ 	  // GMM_ASSERT1(mf_H->get_qdim() == 1,  "Implemented only for mf_H "
+ 	  //	      "a scalar finite element method");
+ 	}
+         GMM_ASSERT1(s = gmm::sqr(mf_u.get_qdim()),
+                     dl[ind] << ": bad format of Dirichlet data. "
+                     "Detected dimension is " << s << " should be "
+                     << size_type(gmm::sqr(mf_u.get_qdim())));
+       }
+ 
+       mesh_region rg(region);
+       mim.linked_mesh().intersect_with_mpi_region(rg);
+ 
+       // Test Neumann term consistency if some computation are needed
+       if (recompute_matrix || (!linear_version && (version & model::BUILD_RHS))
+ 	  || (linear_version && G)) {
+ 	size_type ifb = md.check_Neumann_terms_consistency(vl[0]);
+ 	GMM_ASSERT1(ifb == size_type(-1),
+ 		    "Impossible to build Nitsche's terms for Dirichlet "
+ 		    " condition. At least '"
+ 		    << md.brick_pointer(ifb)->brick_name() << "' is declared "
+ 		    "after Nitsche's brick or do not declare a Neumann term.");
+       }
+ 
+       if (recompute_matrix) {
+ 
+ 	gmm::clear(matl[0]);
+      
+         GMM_TRACE2("Assembly of Nitsche's tangent terms "
+ 		   "for Dirichlet condition");
+ 	asm_Dirichlet_Nitsche_first_tangent_term
+ 	  (matl[0], mim, md, vl[0], mf_u, U, theta, gamma0, H_version,
+ 	   normal_component, mf_H, H, rg);
+ 
+ 	if (theta != scalar_type(0)) {
+ 	  model_real_sparse_matrix B(matl[0]);
+ 	  gmm::scale(B, theta);
+ 	  gmm::add(gmm::transposed(B), matl[0]);
+ 	}
+ 
+ 	asm_Dirichlet_Nitsche_second_tangent_term
+ 	  (matl[0], mim, mf_u, theta, gamma0, H_version, normal_component,
+ 	   mf_H, H, rg);
+ 
+ 	if (theta != scalar_type(0) && !linear_version) {
+ 	  asm_Dirichlet_Nitsche_third_tangent_term
+ 	    (matl[0], mim, md, vl[0], mf_u, U, theta, gamma0, H_version,
+ 	     normal_component, mf_H, H, mf_data, G, rg);
+ 	}
+ 
+ 	for (size_type i = 1; i < vl.size(); ++i) { // Auxilliary variables
+           gmm::clear(matl[i]);
+           if (theta != scalar_type(0) && !linear_version)
+             asm_Dirichlet_Nitsche_fourth_tangent_term
+               (matl[i], mim, md, vl[0], mf_u, U, vl[i],
+                md.mesh_fem_of_variable(vl[i]), theta, gamma0, 
+                H_version, normal_component, mf_H, H, mf_data, G, rg);
+           asm_Dirichlet_Nitsche_fifth_tangent_term
+             (matl[i], mim, md, vl[0], mf_u, U, vl[i],
+              md.mesh_fem_of_variable(vl[i]), theta, gamma0,
+              H_version, normal_component, mf_H, H, rg);
+         }
+       }
+ 
+       if ((!linear_version && (version & model::BUILD_RHS))
+ 	  || (linear_version && G)) {
+ 
+ 	GMM_TRACE2("Assembly of Nitsche's source terms "
+ 		   "for Dirichlet condition");
+ 	asm_Dirichlet_Nitsche_first_rhs_term
+ 	  (vecl[0], mim, md, vl[0], mf_u, U, theta, gamma0, H_version,
+ 	   normal_component, mf_H, H, mf_data, G, linear_version, rg);
+ 	
+ 	if (theta != scalar_type(0)) {
+ 	  asm_Dirichlet_Nitsche_second_rhs_term
+ 	    (vecl[0], mim, md, vl[0], mf_u, U, theta, gamma0, H_version,
+ 	     normal_component, mf_H, H, mf_data, G, linear_version, rg);
+ 	}
+       }
+     }
+ 
+ 
+     Nitsche_Dirichlet_condition_brick(bool H_version_,
+ 				      bool normal_component_,
+ 				      bool is_linear_,
+ 				      scalar_type theta_) {
+       H_version = H_version_;
+       normal_component = normal_component_;
+       // linear_version = false;
+       linear_version = is_linear_;
+       theta = theta_;
+       GMM_ASSERT1(!(H_version && normal_component), "Bad Dirichlet version");
+       set_flags(is_linear_ ? "Dirichlet with Nitsche's method linear brick"
+ 		: "Dirichlet with Nitsche's method nonlinear brick",
+                 linear_version /* is linear*/,
+                 (theta==scalar_type(1)) /* is symmetric */,
+ 		(theta==scalar_type(1)) /* is coercive */,
+                 true /* is real */, false /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
+     }
+   };
+ 
+ 
+   size_type add_Dirichlet_condition_with_Nitsche_method
+   (model &md, const mesh_im &mim, const std::string &varname,
+    const std::string &gamma0name, size_type region, scalar_type theta,
+    const std::string &dataname) {
+ 
+     pbrick pbr = new Nitsche_Dirichlet_condition_brick
+       (false, false, md.check_Neumann_terms_linearity(varname), theta);
+     model::termlist tl;
+     tl.push_back(model::term_description(varname, varname,
+ 					 theta == scalar_type(1)));
+     model::varnamelist vl(1, varname);
+ 
+     std::vector<std::string> aux_vars;
+     md.auxilliary_variables_of_Neumann_terms(varname, aux_vars);
+     for (size_type i = 0; i < aux_vars.size(); ++i) {
+       vl.push_back(aux_vars[i]);
+       tl.push_back(model::term_description(varname, aux_vars[i], false));
+     }
+ 
+     model::varnamelist dl;
+     dl.push_back(gamma0name);
+     if (dataname.size()) dl.push_back(dataname);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+   }
+ 
+ 
+   size_type add_normal_Dirichlet_condition_with_Nitsche_method
+   (model &md, const mesh_im &mim, const std::string &varname,
+    const std::string &gamma0name, size_type region, scalar_type theta,
+    const std::string &dataname) {
+     pbrick pbr = new Nitsche_Dirichlet_condition_brick
+       (false, true, md.check_Neumann_terms_linearity(varname), theta);
+     model::termlist tl;
+     tl.push_back(model::term_description(varname, varname,
+ 					 theta == scalar_type(1)));
+     model::varnamelist vl(1, varname);
+ 
+     std::vector<std::string> aux_vars;
+     md.auxilliary_variables_of_Neumann_terms(varname, aux_vars);
+     for (size_type i = 0; i < aux_vars.size(); ++i) {
+       vl.push_back(aux_vars[i]);
+       tl.push_back(model::term_description(varname, aux_vars[i], false));
+     }
+ 
+     model::varnamelist dl;
+     dl.push_back(gamma0name);
+     if (dataname.size()) dl.push_back(dataname);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+   }
+ 
+   size_type add_generalized_Dirichlet_condition_with_Nitsche_method
+   (model &md, const mesh_im &mim, const std::string &varname,
+    const std::string &gamma0name, size_type region, scalar_type theta,
+    const std::string &dataname, const std::string &Hname) {
+     pbrick pbr = new Nitsche_Dirichlet_condition_brick
+       (true, false, md.check_Neumann_terms_linearity(varname), theta);
+     model::termlist tl;
+     tl.push_back(model::term_description(varname, varname,
+ 					 theta == scalar_type(1)));
+     model::varnamelist vl(1, varname);
+ 
+     std::vector<std::string> aux_vars;
+     md.auxilliary_variables_of_Neumann_terms(varname, aux_vars);
+     for (size_type i = 0; i < aux_vars.size(); ++i) {
+       vl.push_back(aux_vars[i]);
+       tl.push_back(model::term_description(varname, aux_vars[i], false));
+     }
+ 
+     model::varnamelist dl;
+     dl.push_back(gamma0name);
+     dl.push_back(dataname);
+     dl.push_back(Hname);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+   }
+ 
+   // ----------------------------------------------------------------------
+   //
+   // Pointwise constraints brick
+   //
+   // ----------------------------------------------------------------------
+   // Two variables : with multipliers
+   // One variable : penalization
+ 
+   struct pointwise_constraints_brick : public virtual_brick {
+     
+     mutable gmm::row_matrix<model_real_sparse_vector> rB;
+     mutable gmm::row_matrix<model_complex_sparse_vector> cB;
+ 
+     virtual void asm_real_tangent_terms(const model &md, size_type ib,
+                                         const model::varnamelist &vl,
+                                         const model::varnamelist &dl,
+                                         const model::mimlist &mims,
+                                         model::real_matlist &matl,
+                                         model::real_veclist &vecl,
+                                         model::real_veclist &rvecl,
+                                         size_type,
+                                         build_version version) const {
+ 
+       GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
+                   "Pointwize constraints brick has only one term");
+       GMM_ASSERT1(mims.size() == 0,
+                   "Pointwize constraints brick does not need a mesh_im");
+       GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2,
+                   "Wrong number of variables for pointwize constraints brick");
+       bool penalized = (vl.size() == 1);
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+       dim_type N = mf_u.linked_mesh().dim(), Q = mf_u.get_qdim(), ind_pt = 0;
+       size_type dlsize = size_type((penalized ? 1 : 0) + 1 + (Q > 1 ? 1 : 0));
+       GMM_ASSERT1(dl.size() == dlsize || dl.size() == dlsize+1,
+ 		  "Wrong number of data for pointwize constraints brick");
+ 
+       
+       const model_real_plain_vector *COEFF = 0;
+       if (penalized) {
+         COEFF = &(md.real_variable(dl[0]));
+ 	ind_pt = 1;
+         GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
+                     "Data for coefficient should be a scalar");
+       }
+ 
+       const model_real_plain_vector &PT = md.real_variable(dl[ind_pt]);
+       size_type nb_co = gmm::vect_size(PT) / N;
+       
+       dim_type ind_unitv = dim_type((Q > 1) ? ind_pt+1 : 0);
+       const model_real_plain_vector &unitv =md.real_variable(dl[ind_unitv]);
+       GMM_ASSERT1((!ind_unitv || gmm::vect_size(unitv) == nb_co * Q),
+ 		  "Wrong size for vector of unit vectors");
+       
+       dim_type ind_rhs = dim_type((Q > 1) ? ind_pt+2 : ind_pt+1);
+       if (dl.size() < size_type(ind_rhs + 1)) ind_rhs = 0;
+       const model_real_plain_vector &rhs =  md.real_variable(dl[ind_rhs]);
+       GMM_ASSERT1((!ind_rhs || gmm::vect_size(rhs) == nb_co),
+ 		  "Wrong size for vector of rhs");
+ 
+       bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
+         || (penalized && (md.is_var_newer_than_brick(dl[ind_pt], ib)
+ 			  || md.is_var_newer_than_brick(dl[ind_unitv], ib)
+ 			  || md.is_var_newer_than_brick(dl[ind_rhs], ib)));
+       
+       if (recompute_matrix) {
+ 	gmm::row_matrix<model_real_sparse_vector> BB(nb_co*Q, mf_u.nb_dof());
+ 	gmm::clear(rB); gmm::resize(rB, nb_co, mf_u.nb_dof());
+ 
+ 	dal::bit_vector dof_untouched;
+ 	getfem::mesh_trans_inv mti(mf_u.linked_mesh());
+ 	base_node pt(N);
+ 	for (size_type i = 0; i < nb_co; ++i) {
+ 	  gmm::copy(gmm::sub_vector(PT, gmm::sub_interval(i*N, N)), pt);
+ 	  mti.add_point(pt);
+ 	}
+ 	gmm::row_matrix<model_real_sparse_vector> &BBB = ((Q > 1) ? BB : rB);
+ 	model_real_plain_vector vv;
+ 	interpolation(mf_u, mti, vv, vv, BBB,  1, 1, &dof_untouched);
+ 	GMM_ASSERT1(dof_untouched.card() == 0,
+ 		    "Pointwize constraints : some of the points are outside "
+ 		    "the mesh: " << dof_untouched);
+ 	
+ 	if (Q > 1) {
+ 	  for (size_type i = 0; i < nb_co; ++i)
+ 	    for (size_type q = 0; q < Q; ++q)
+ 	      gmm::add(gmm::scaled(gmm::mat_row(BB, i*Q+q), unitv[i*Q+q]),
+ 		       gmm::mat_row(rB, i));
+ 	}
+         if (penalized) {
+           gmm::mult(gmm::transposed(rB), rB, matl[0]);
+           gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
+         } else
+ 	  gmm::copy(rB, matl[0]);
+       }
+ 
+       if (ind_rhs) {
+         if (penalized) {
+           gmm::mult(gmm::transposed(rB), rhs, vecl[0]);
+           gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
+         }
+ 	else gmm::copy(rhs, vecl[0]);
+       }
+       else gmm::clear(vecl[0]);
+     }
+ 
+     virtual void asm_complex_tangent_terms(const model &md, size_type ib,
+                                            const model::varnamelist &vl,
+                                            const model::varnamelist &dl,
+                                            const model::mimlist &mims,
+                                            model::complex_matlist &matl,
+                                            model::complex_veclist &vecl,
+                                            model::complex_veclist &,
+                                            size_type,
+                                            build_version version) const {
+       GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
+                   "Pointwize constraints brick only one term");
+       GMM_ASSERT1(mims.size() == 0,
+                   "Pointwize constraints brick does not need a mesh_im");
+       GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2,
+                   "Wrong number of variables for pointwize constraints brick");
+       bool penalized = (vl.size() == 1);
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+       dim_type N = mf_u.linked_mesh().dim(), Q = mf_u.get_qdim(), ind_pt = 0;
+       size_type dlsize = size_type((penalized ? 1 : 0) + 1 + (Q > 1 ? 1 : 0));
+       GMM_ASSERT1(dl.size() == dlsize || dl.size() == dlsize+1,
+ 		  "Wrong number of data for pointwize constraints brick");
+ 
+       
+       const model_complex_plain_vector *COEFF = 0;
+       if (penalized) {
+         COEFF = &(md.complex_variable(dl[0]));
+ 	ind_pt = 1;
+         GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
+                     "Data for coefficient should be a scalar");
+       }
+ 
+       const model_complex_plain_vector &PT = md.complex_variable(dl[ind_pt]);
+       size_type nb_co = gmm::vect_size(PT) / N;
+       
+       dim_type ind_unitv = dim_type((Q > 1) ? ind_pt+1 : 0);
+       const model_complex_plain_vector &unitv
+ 	= md.complex_variable(dl[ind_unitv]);
+       GMM_ASSERT1((!ind_unitv || gmm::vect_size(unitv) == nb_co * Q),
+ 		  "Wrong size for vector of unit vectors");
+       
+       dim_type ind_rhs = dim_type((Q > 1) ? ind_pt+2 : ind_pt+1);
+       if (dl.size() < size_type(ind_rhs + 1)) ind_rhs = 0;
+       const model_complex_plain_vector &rhs
+ 	= md.complex_variable(dl[ind_rhs]);
+       GMM_ASSERT1((!ind_rhs || gmm::vect_size(rhs) == nb_co),
+ 		  "Wrong size for vector of rhs");
+       
+       bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
+         || (penalized && (md.is_var_newer_than_brick(dl[ind_pt], ib)
+ 			  || md.is_var_newer_than_brick(dl[ind_unitv], ib)
+ 			  || md.is_var_newer_than_brick(dl[ind_rhs], ib)));
+ 
+       if (recompute_matrix) {
+ 	gmm::row_matrix<model_complex_sparse_vector> BB(nb_co*Q,mf_u.nb_dof());
+ 	gmm::clear(cB); gmm::resize(cB, nb_co, mf_u.nb_dof());
+ 	dal::bit_vector dof_untouched;
+ 	getfem::mesh_trans_inv mti(mf_u.linked_mesh());
+ 	base_node pt(N);
+ 	for (size_type i = 0; i < nb_co; ++i) {
+ 	  gmm::copy(gmm::real_part(gmm::sub_vector(PT,
+ 				   gmm::sub_interval(i*N, N))), pt);
+ 	  mti.add_point(pt);
+ 	}
+ 	gmm::row_matrix<model_complex_sparse_vector> &BBB = ((Q > 1) ? BB :cB);
+ 	model_complex_plain_vector vv;
+ 	interpolation(mf_u, mti, vv, vv, BBB,  1, 1, &dof_untouched);
+ 	GMM_ASSERT1(dof_untouched.card() == 0,
+ 		    "Pointwize constraints : some of the points are outside "
+ 		    "the mesh: " << dof_untouched);
+ 	
+ 	if (Q > 1) {
+ 	  for (size_type i = 0; i < nb_co; ++i)
+ 	    for (size_type q = 0; q < Q; ++q)
+ 	      gmm::add(gmm::scaled(gmm::mat_row(BB, i*Q+q), unitv[i*Q+q]),
+ 		       gmm::mat_row(cB, i));
+ 	}
+ 
+         if (penalized) {
+           gmm::mult(gmm::transposed(cB), cB, matl[0]);
+           gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
+         } else
+ 	  gmm::copy(cB, matl[0]);
+       }
+ 
+       
+       if (ind_rhs) {
+         if (penalized) {
+           gmm::mult(gmm::transposed(cB), rhs, vecl[0]);
+           gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
+         }
+ 	else gmm::copy(rhs, vecl[0]);
+       }
+       else gmm::clear(vecl[0]);
+     }
+ 
+     pointwise_constraints_brick(bool penalized) {
+       set_flags(penalized ? "Pointwise cosntraints with penalization brick"
+                           : "Pointwise cosntraints with multipliers brick",
+                 true /* is linear*/,
+                 true /* is symmetric */, penalized /* is coercive */,
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
+     }
+   };
+ 
+ 
+   size_type add_pointwise_constraints_with_penalization
+   (model &md, const std::string &varname,
+    scalar_type penalisation_coeff, const std::string &dataname_pt,
+    const std::string &dataname_unitv, const std::string &dataname_val) {
+     std::string coeffname = md.new_name("penalization_on_" + varname);
+     md.add_fixed_size_data(coeffname, 1);
+     if (md.is_complex())
+       md.set_complex_variable(coeffname)[0] = penalisation_coeff;
+     else
+       md.set_real_variable(coeffname)[0] = penalisation_coeff;
+     pbrick pbr = new pointwise_constraints_brick(true);
+     model::termlist tl;
+     tl.push_back(model::term_description(varname, varname, true));
+     model::varnamelist vl(1, varname);
+     model::varnamelist dl(1, coeffname);
+     dl.push_back(dataname_pt);
+     const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
+     if (mf_u.get_qdim() > 1) dl.push_back(dataname_unitv);
+     if (dataname_val.size() > 0) dl.push_back(dataname_val);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(), size_type(-1));
+   }
+ 
+   size_type add_pointwise_constraints_with_given_multipliers
+   (model &md, const std::string &varname,
+    const std::string &multname, const std::string &dataname_pt,
+    const std::string &dataname_unitv, const std::string &dataname_val) {
+     pbrick pbr = new  pointwise_constraints_brick(false);
+     model::termlist tl;
+     tl.push_back(model::term_description(multname, varname, true));
      model::varnamelist vl(1, varname);
-     model::varnamelist dl(1, coeffname);
-     dl.push_back(dataname);
-     dl.push_back(Hname);
-     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
+     vl.push_back(multname);
+     model::varnamelist dl(1, dataname_pt);
+     const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
+     if (mf_u.get_qdim() > 1) dl.push_back(dataname_unitv);
+     if (dataname_val.size() > 0) dl.push_back(dataname_val);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(), size_type(-1));
    }
  
-   void change_penalization_coeff(model &md, size_type ind_brick,
-                                  scalar_type penalisation_coeff) {
-     const std::string &coeffname = md.dataname_of_brick(ind_brick, 0);
-     if (!md.is_complex()) {
-       model_real_plain_vector &d = md.set_real_variable(coeffname);
-       GMM_ASSERT1(gmm::vect_size(d)==1,
-                   "Wrong coefficient size, may be not a Dirichlet brick "
-                   "with penalization");
-       d[0] = penalisation_coeff;
-     }
-     else {
-       model_complex_plain_vector &d = md.set_complex_variable(coeffname);
-       GMM_ASSERT1(gmm::vect_size(d)==1,
-                   "Wrong coefficient size, may be not a Dirichlet brick "
-                   "with penalization");
-       d[0] = penalisation_coeff;
-     }
+   size_type add_pointwise_constraints_with_multipliers
+   (model &md, const std::string &varname, const std::string &dataname_pt,
+    const std::string &dataname_unitv, const std::string &dataname_val) {
+     std::string multname = md.new_name("mult_on_" + varname);
+     const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
+     size_type nb_co =
+       ((md.is_complex()) ? gmm::vect_size(md.complex_variable(dataname_pt))
+        : gmm::vect_size(md.real_variable(dataname_pt)))
+       / mf_u.linked_mesh().dim();
+     md.add_fixed_size_variable(multname, nb_co);
+     return add_pointwise_constraints_with_given_multipliers
+       (md, varname, multname, dataname_pt, dataname_unitv, dataname_val);
    }
  
+ 
++>>>>>>> upstream
    // ----------------------------------------------------------------------
    //
 -  // Helmholtz brick
 +  // Pointwise constraints brick
    //
    // ----------------------------------------------------------------------
 +  // Two variables : with multipliers
 +  // One variable : penalization
  
++<<<<<<< HEAD
 +  struct pointwise_constraints_brick : public virtual_brick {
 +    
 +    mutable gmm::row_matrix<model_real_sparse_vector> rB;
 +    mutable gmm::row_matrix<model_complex_sparse_vector> cB;
++=======
+   struct Helmholtz_brick : public virtual_brick {
+ 
+     virtual void asm_real_tangent_terms(const model &md, size_type,
+                                         const model::varnamelist &vl,
+                                         const model::varnamelist &dl,
+                                         const model::mimlist &mims,
+                                         model::real_matlist &matl,
+                                         model::real_veclist &,
+                                         model::real_veclist &,
+                                         size_type region,
+                                         build_version) const {
+       GMM_ASSERT1(matl.size() == 1,
+                   "Helmholtz brick has one and only one term");
+       GMM_ASSERT1(mims.size() == 1,
+                   "Helmholtz brick need one and only one mesh_im");
+       GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
+                   "Wrong number of variables for Helmholtz brick");
++>>>>>>> upstream
  
 +    virtual void asm_real_tangent_terms(const model &md, size_type ib,
 +                                        const model::varnamelist &vl,
 +                                        const model::varnamelist &dl,
 +                                        const model::mimlist &mims,
 +                                        model::real_matlist &matl,
 +                                        model::real_veclist &vecl,
 +                                        model::real_veclist &,
 +                                        size_type,
 +                                        build_version version) const {
 +      GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
 +                  "Pointwize constraints brick only one term");
 +      GMM_ASSERT1(mims.size() == 0,
 +                  "Pointwize constraints brick does not need a mesh_im");
 +      GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2,
 +                  "Wrong number of variables for pointwize constraints brick");
 +      bool penalized = (vl.size() == 1);
        const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
 -      const mesh &m = mf_u.linked_mesh();
 -      size_type Q = mf_u.get_qdim(), s = 1;
 -      GMM_ASSERT1(Q == 1, "Helmholtz brick is only for scalar field, sorry.");
 -      const mesh_im &mim = *mims[0];
 -      const mesh_fem *mf_a = 0;
 -      mesh_region rg(region);
 -      m.intersect_with_mpi_region(rg);
 -      const model_real_plain_vector *A = &(md.real_variable(dl[0]));
 -      mf_a = md.pmesh_fem_of_variable(dl[0]);
 -      s = gmm::vect_size(*A);
 -      if (mf_a) s = s * mf_a->get_qdim() / mf_a->nb_dof();
 -
 -      if (s == 1) {
 -        GMM_TRACE2("Stiffness matrix assembly for Helmholtz problem");
 -        gmm::clear(matl[0]);
 -        model_real_plain_vector A2(gmm::vect_size(*A));
 -        for (size_type i=0; i < gmm::vect_size(*A); ++i) // Not valid for
 -          A2[i] = gmm::sqr((*A)[i]); // non lagrangian fem ...
 -        if (mf_a)
 -          asm_Helmholtz(matl[0], mim, mf_u, *mf_a, A2, rg);
 -        else
 -          asm_homogeneous_Helmholtz(matl[0], mim, mf_u, A2, rg);
 -      } else
 -        GMM_ASSERT1(false, "Bad format Helmholtz brick coefficient");
 -    }
 +      dim_type N = mf_u.linked_mesh().dim(), Q = mf_u.get_qdim(), ind_pt = 0;
 +      size_type dlsize = size_type((penalized ? 1 : 0) + 1 + (Q > 1 ? 1 : 0));
 +      GMM_ASSERT1(dl.size() == dlsize || dl.size() == dlsize+1,
 +		  "Wrong number of data for pointwize constraints brick");
  
 -    virtual void asm_complex_tangent_terms(const model &md, size_type,
 -                                           const model::varnamelist &vl,
 -                                           const model::varnamelist &dl,
 -                                           const model::mimlist &mims,
 -                                           model::complex_matlist &matl,
 -                                           model::complex_veclist &,
 -                                           model::complex_veclist &,
 -                                           size_type region,
 -                                           build_version) const {
 -      GMM_ASSERT1(matl.size() == 1,
 -                  "Helmholtz brick has one and only one term");
 -      GMM_ASSERT1(mims.size() == 1,
 -                  "Helmholtz brick need one and only one mesh_im");
 -      GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
 -                  "Wrong number of variables for Helmholtz brick");
 +      
 +      const model_real_plain_vector *COEFF = 0;
 +      if (penalized) {
 +        COEFF = &(md.real_variable(dl[0]));
 +	ind_pt = 1;
 +        GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
 +                    "Data for coefficient should be a scalar");
 +      }
  
 -      const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
 -      const mesh &m = mf_u.linked_mesh();
 -      size_type Q = mf_u.get_qdim(), s = 1;
 -      GMM_ASSERT1(Q == 1, "Helmholtz brick is only for scalar field, sorry.");
 -      const mesh_im &mim = *mims[0];
 +      const model_real_plain_vector &PT = md.real_variable(dl[ind_pt]);
 +      size_type nb_co = gmm::vect_size(PT) / N;
 +      
 +      dim_type ind_unitv = dim_type((Q > 1) ? ind_pt+1 : 0);
 +      const model_real_plain_vector &unitv =md.real_variable(dl[ind_unitv]);
 +      GMM_ASSERT1((!ind_unitv || gmm::vect_size(unitv) == nb_co * Q),
 +		  "Wrong size for vector of unit vectors");
 +      
 +      dim_type ind_rhs = dim_type((Q > 1) ? ind_pt+2 : ind_pt+1);
 +      if (dl.size() < size_type(ind_rhs + 1)) ind_rhs = 0;
 +      const model_real_plain_vector &rhs =  md.real_variable(dl[ind_rhs]);
 +      GMM_ASSERT1((!ind_rhs || gmm::vect_size(rhs) == nb_co),
 +		  "Wrong size for vector of rhs");
 +
 +      
 +      bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
 +        || (penalized && (md.is_var_newer_than_brick(dl[ind_pt], ib)
 +			  || md.is_var_newer_than_brick(dl[ind_unitv], ib)
 +			  || md.is_var_newer_than_brick(dl[ind_rhs], ib)));
 +      
 +      if (recompute_matrix) {
 +	gmm::row_matrix<model_real_sparse_vector> BB(nb_co*Q, mf_u.nb_dof());
 +	gmm::clear(rB); gmm::resize(rB, nb_co, mf_u.nb_dof());
 +
 +	dal::bit_vector dof_untouched;
 +	getfem::mesh_trans_inv mti(mf_u.linked_mesh());
 +	base_node pt(N);
 +	for (size_type i = 0; i < nb_co; ++i) {
 +	  gmm::copy(gmm::sub_vector(PT, gmm::sub_interval(i*N, N)), pt);
 +	  mti.add_point(pt);
 +	}
 +	gmm::row_matrix<model_real_sparse_vector> &BBB = ((Q > 1) ? BB : rB);
 +	model_real_plain_vector vv;
 +	interpolation(mf_u, mti, vv, vv, BBB,  1, 1, &dof_untouched);
 +	GMM_ASSERT1(dof_untouched.card() == 0,
 +		    "Pointwize constraints : some of the points are outside "
 +		    "the mesh: " << dof_untouched);
 +	
 +	if (Q > 1) {
 +	  for (size_type i = 0; i < nb_co; ++i)
 +	    for (size_type q = 0; q < Q; ++q)
 +	      gmm::add(gmm::scaled(gmm::mat_row(BB, i*Q+q), unitv[i*Q+q]),
 +		       gmm::mat_row(rB, i));
 +	}
 +        if (penalized) {
 +          gmm::mult(gmm::transposed(rB), rB, matl[0]);
 +          gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
 +        } else
 +	  gmm::copy(rB, matl[0]);
 +      }
 +
 +      if (ind_rhs) {
 +        if (penalized) {
 +          gmm::mult(gmm::transposed(rB), rhs, vecl[0]);
 +          gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
 +        }
 +	else gmm::copy(rhs, vecl[0]);
 +      }
 +      else gmm::clear(vecl[0]);
 +    }
 +
 +    virtual void asm_complex_tangent_terms(const model &md, size_type ib,
 +                                           const model::varnamelist &vl,
 +                                           const model::varnamelist &dl,
 +                                           const model::mimlist &mims,
 +                                           model::complex_matlist &matl,
 +                                           model::complex_veclist &vecl,
 +                                           model::complex_veclist &,
 +                                           size_type,
 +                                           build_version version) const {
 +      GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
 +                  "Pointwize constraints brick only one term");
 +      GMM_ASSERT1(mims.size() == 0,
 +                  "Pointwize constraints brick does not need a mesh_im");
 +      GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2,
 +                  "Wrong number of variables for pointwize constraints brick");
 +      bool penalized = (vl.size() == 1);
 +      const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
 +      dim_type N = mf_u.linked_mesh().dim(), Q = mf_u.get_qdim(), ind_pt = 0;
 +      size_type dlsize = size_type((penalized ? 1 : 0) + 1 + (Q > 1 ? 1 : 0));
 +      GMM_ASSERT1(dl.size() == dlsize || dl.size() == dlsize+1,
 +		  "Wrong number of data for pointwize constraints brick");
 +
 +      
 +      const model_complex_plain_vector *COEFF = 0;
 +      if (penalized) {
 +        COEFF = &(md.complex_variable(dl[0]));
 +	ind_pt = 1;
 +        GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
 +                    "Data for coefficient should be a scalar");
 +      }
 +
 +      const model_complex_plain_vector &PT = md.complex_variable(dl[ind_pt]);
 +      size_type nb_co = gmm::vect_size(PT) / N;
 +      
 +      dim_type ind_unitv = dim_type((Q > 1) ? ind_pt+1 : 0);
 +      const model_complex_plain_vector &unitv
 +	= md.complex_variable(dl[ind_unitv]);
 +      GMM_ASSERT1((!ind_unitv || gmm::vect_size(unitv) == nb_co * Q),
 +		  "Wrong size for vector of unit vectors");
 +      
 +      dim_type ind_rhs = dim_type((Q > 1) ? ind_pt+2 : ind_pt+1);
 +      if (dl.size() < size_type(ind_rhs + 1)) ind_rhs = 0;
 +      const model_complex_plain_vector &rhs
 +	= md.complex_variable(dl[ind_rhs]);
 +      GMM_ASSERT1((!ind_rhs || gmm::vect_size(rhs) == nb_co),
 +		  "Wrong size for vector of rhs");
 +      
 +      bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
 +        || (penalized && (md.is_var_newer_than_brick(dl[ind_pt], ib)
 +			  || md.is_var_newer_than_brick(dl[ind_unitv], ib)
 +			  || md.is_var_newer_than_brick(dl[ind_rhs], ib)));
 +
 +      if (recompute_matrix) {
 +	gmm::row_matrix<model_complex_sparse_vector> BB(nb_co*Q,mf_u.nb_dof());
 +	gmm::clear(cB); gmm::resize(cB, nb_co, mf_u.nb_dof());
 +	dal::bit_vector dof_untouched;
 +	getfem::mesh_trans_inv mti(mf_u.linked_mesh());
 +	base_node pt(N);
 +	for (size_type i = 0; i < nb_co; ++i) {
 +	  gmm::copy(gmm::real_part(gmm::sub_vector(PT,
 +				   gmm::sub_interval(i*N, N))), pt);
 +	  mti.add_point(pt);
 +	}
 +	gmm::row_matrix<model_complex_sparse_vector> &BBB = ((Q > 1) ? BB :cB);
 +	model_complex_plain_vector vv;
 +	interpolation(mf_u, mti, vv, vv, BBB,  1, 1, &dof_untouched);
 +	GMM_ASSERT1(dof_untouched.card() == 0,
 +		    "Pointwize constraints : some of the points are outside "
 +		    "the mesh: " << dof_untouched);
 +	
 +	if (Q > 1) {
 +	  for (size_type i = 0; i < nb_co; ++i)
 +	    for (size_type q = 0; q < Q; ++q)
 +	      gmm::add(gmm::scaled(gmm::mat_row(BB, i*Q+q), unitv[i*Q+q]),
 +		       gmm::mat_row(cB, i));
 +	}
 +
 +        if (penalized) {
 +          gmm::mult(gmm::transposed(cB), cB, matl[0]);
 +          gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
 +        } else
 +	  gmm::copy(cB, matl[0]);
 +      }
 +
 +      
 +      if (ind_rhs) {
 +        if (penalized) {
 +          gmm::mult(gmm::transposed(cB), rhs, vecl[0]);
 +          gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
 +        }
 +	else gmm::copy(rhs, vecl[0]);
 +      }
 +      else gmm::clear(vecl[0]);
 +    }
 +
 +    pointwise_constraints_brick(bool penalized) {
 +      set_flags(penalized ? "Pointwise cosntraints with penalization brick"
 +                          : "Pointwise cosntraints with multipliers brick",
 +                true /* is linear*/,
 +                true /* is symmetric */, penalized /* is coercive */,
 +                true /* is real */, true /* is complex */);
 +    }
 +  };
 +
 +
 +  size_type add_pointwise_constraints_with_penalization
 +  (model &md, const std::string &varname,
 +   scalar_type penalisation_coeff, const std::string &dataname_pt,
 +   const std::string &dataname_unitv, const std::string &dataname_val) {
 +    std::string coeffname = md.new_name("penalization_on_" + varname);
 +    md.add_fixed_size_data(coeffname, 1);
 +    if (md.is_complex())
 +      md.set_complex_variable(coeffname)[0] = penalisation_coeff;
 +    else
 +      md.set_real_variable(coeffname)[0] = penalisation_coeff;
 +    pbrick pbr = new pointwise_constraints_brick(true);
 +    model::termlist tl;
 +    tl.push_back(model::term_description(varname, varname, true));
 +    model::varnamelist vl(1, varname);
 +    model::varnamelist dl(1, coeffname);
 +    dl.push_back(dataname_pt);
 +    const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
 +    if (mf_u.get_qdim() > 1) dl.push_back(dataname_unitv);
 +    if (dataname_val.size() > 0) dl.push_back(dataname_val);
 +    return md.add_brick(pbr, vl, dl, tl, model::mimlist(), size_type(-1));
 +  }
 +
 +  size_type add_pointwise_constraints_with_given_multipliers
 +  (model &md, const std::string &varname,
 +   const std::string &multname, const std::string &dataname_pt,
 +   const std::string &dataname_unitv, const std::string &dataname_val) {
 +    pbrick pbr = new  pointwise_constraints_brick(false);
 +    model::termlist tl;
 +    tl.push_back(model::term_description(multname, varname, true));
 +    model::varnamelist vl(1, varname);
 +    vl.push_back(multname);
 +    model::varnamelist dl(1, dataname_pt);
 +    const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
 +    if (mf_u.get_qdim() > 1) dl.push_back(dataname_unitv);
 +    if (dataname_val.size() > 0) dl.push_back(dataname_val);
 +    return md.add_brick(pbr, vl, dl, tl, model::mimlist(), size_type(-1));
 +  }
 +
 +  size_type add_pointwise_constraints_with_multipliers
 +  (model &md, const std::string &varname, const std::string &dataname_pt,
 +   const std::string &dataname_unitv, const std::string &dataname_val) {
 +    std::string multname = md.new_name("mult_on_" + varname);
 +    const mesh_fem &mf_u = md.mesh_fem_of_variable(varname);
 +    size_type nb_co =
 +      ((md.is_complex()) ? gmm::vect_size(md.complex_variable(dataname_pt))
 +       : gmm::vect_size(md.real_variable(dataname_pt)))
 +      / mf_u.linked_mesh().dim();
 +    md.add_fixed_size_variable(multname, nb_co);
 +    return add_pointwise_constraints_with_given_multipliers
 +      (md, varname, multname, dataname_pt, dataname_unitv, dataname_val);
 +  }
 +
 +
 +  // ----------------------------------------------------------------------
 +  //
 +  // Helmholtz brick
 +  //
 +  // ----------------------------------------------------------------------
 +
 +  struct Helmholtz_brick : public virtual_brick {
 +
 +    virtual void asm_real_tangent_terms(const model &md, size_type,
 +                                        const model::varnamelist &vl,
 +                                        const model::varnamelist &dl,
 +                                        const model::mimlist &mims,
 +                                        model::real_matlist &matl,
 +                                        model::real_veclist &,
 +                                        model::real_veclist &,
 +                                        size_type region,
 +                                        build_version) const {
 +      GMM_ASSERT1(matl.size() == 1,
 +                  "Helmholtz brick has one and only one term");
 +      GMM_ASSERT1(mims.size() == 1,
 +                  "Helmholtz brick need one and only one mesh_im");
 +      GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
 +                  "Wrong number of variables for Helmholtz brick");
 +
 +      const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
 +      const mesh &m = mf_u.linked_mesh();
 +      size_type Q = mf_u.get_qdim(), s = 1;
 +      GMM_ASSERT1(Q == 1, "Helmholtz brick is only for scalar field, sorry.");
 +      const mesh_im &mim = *mims[0];
 +      const mesh_fem *mf_a = 0;
 +      mesh_region rg(region);
 +      m.intersect_with_mpi_region(rg);
 +      const model_real_plain_vector *A = &(md.real_variable(dl[0]));
 +      mf_a = md.pmesh_fem_of_variable(dl[0]);
 +      s = gmm::vect_size(*A);
 +      if (mf_a) s = s * mf_a->get_qdim() / mf_a->nb_dof();
 +
 +      if (s == 1) {
 +        GMM_TRACE2("Stiffness matrix assembly for Helmholtz problem");
 +        gmm::clear(matl[0]);
 +        model_real_plain_vector A2(gmm::vect_size(*A));
 +        for (size_type i=0; i < gmm::vect_size(*A); ++i) // Not valid for
 +          A2[i] = gmm::sqr((*A)[i]); // non lagrangian fem ...
 +        if (mf_a)
 +          asm_Helmholtz(matl[0], mim, mf_u, *mf_a, A2, rg);
 +        else
 +          asm_homogeneous_Helmholtz(matl[0], mim, mf_u, A2, rg);
 +      } else
 +        GMM_ASSERT1(false, "Bad format Helmholtz brick coefficient");
 +    }
 +
 +    virtual void asm_complex_tangent_terms(const model &md, size_type,
 +                                           const model::varnamelist &vl,
 +                                           const model::varnamelist &dl,
 +                                           const model::mimlist &mims,
 +                                           model::complex_matlist &matl,
 +                                           model::complex_veclist &,
 +                                           model::complex_veclist &,
 +                                           size_type region,
 +                                           build_version) const {
 +      GMM_ASSERT1(matl.size() == 1,
 +                  "Helmholtz brick has one and only one term");
 +      GMM_ASSERT1(mims.size() == 1,
 +                  "Helmholtz brick need one and only one mesh_im");
 +      GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
 +                  "Wrong number of variables for Helmholtz brick");
 +
 +      const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
 +      const mesh &m = mf_u.linked_mesh();
 +      size_type Q = mf_u.get_qdim(), s = 1;
 +      GMM_ASSERT1(Q == 1, "Helmholtz brick is only for scalar field, sorry.");
 +      const mesh_im &mim = *mims[0];
        const mesh_fem *mf_a = 0;
        mesh_region rg(region);
        m.intersect_with_mpi_region(rg);
@@@ -2597,328 -4266,330 +4993,537 @@@
                  true /* is real */, true /* is complex */);
      }
  
-   };
+   };
+ 
+   size_type add_Helmholtz_brick(model &md, const mesh_im &mim,
+                                 const std::string &varname,
+                                 const std::string &dataname,
+                                 size_type region) {
+     pbrick pbr = new Helmholtz_brick;
+     model::termlist tl;
+     tl.push_back(model::term_description(varname, varname, true));
+     return md.add_brick(pbr, model::varnamelist(1, varname),
+                         model::varnamelist(1, dataname), tl,
+                         model::mimlist(1, &mim), region);
+   }
+ 
+ 
+ 
+   // ----------------------------------------------------------------------
+   //
+   // Fourier-Robin brick
+   //
+   // ----------------------------------------------------------------------
+ 
+   struct Fourier_Robin_brick : public virtual_brick {
+ 
+     virtual void asm_real_tangent_terms(const model &md, size_type,
+                                         const model::varnamelist &vl,
+                                         const model::varnamelist &dl,
+                                         const model::mimlist &mims,
+                                         model::real_matlist &matl,
+                                         model::real_veclist &,
+                                         model::real_veclist &,
+                                         size_type region,
+                                         build_version) const {
+       GMM_ASSERT1(matl.size() == 1,
+                   "Fourier-Robin brick has one and only one term");
+       GMM_ASSERT1(mims.size() == 1,
+                   "Fourier-Robin brick need one and only one mesh_im");
+       GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
+                   "Wrong number of variables for Fourier-Robin brick");
+ 
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+       const mesh &m = mf_u.linked_mesh();
+       size_type Q = mf_u.get_qdim(), s = 1;
+       const mesh_im &mim = *mims[0];
+       const mesh_fem *mf_a = 0;
+       mesh_region rg(region);
+       m.intersect_with_mpi_region(rg);
+       const model_real_plain_vector *A = &(md.real_variable(dl[0]));
+       mf_a = md.pmesh_fem_of_variable(dl[0]);
+       s = gmm::vect_size(*A);
+       if (mf_a) s = s * mf_a->get_qdim() / mf_a->nb_dof();
+       GMM_ASSERT1(s == Q*Q,
+                   "Bad format Fourier-Robin brick coefficient");
+ 
+       GMM_TRACE2("Fourier-Robin term assembly");
+       gmm::clear(matl[0]);
+       if (mf_a)
+         asm_qu_term(matl[0], mim, mf_u, *mf_a, *A, rg);
+       else
+         asm_homogeneous_qu_term(matl[0], mim, mf_u, *A, rg);
+     }
+ 
+     virtual void asm_complex_tangent_terms(const model &md, size_type,
+                                            const model::varnamelist &vl,
+                                            const model::varnamelist &dl,
+                                            const model::mimlist &mims,
+                                            model::complex_matlist &matl,
+                                            model::complex_veclist &,
+                                            model::complex_veclist &,
+                                            size_type region,
+                                            build_version) const {
+       GMM_ASSERT1(matl.size() == 1,
+                   "Fourier-Robin brick has one and only one term");
+       GMM_ASSERT1(mims.size() == 1,
+                   "Fourier-Robin brick need one and only one mesh_im");
+       GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
+                   "Wrong number of variables for Fourier-Robin brick");
+ 
+       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
+       const mesh &m = mf_u.linked_mesh();
+       size_type Q = mf_u.get_qdim(), s = 1;
+       const mesh_im &mim = *mims[0];
+       const mesh_fem *mf_a = 0;
+       mesh_region rg(region);
+       m.intersect_with_mpi_region(rg);
+       const model_complex_plain_vector *A = &(md.complex_variable(dl[0]));
+       mf_a = md.pmesh_fem_of_variable(dl[0]);
+       s = gmm::vect_size(*A);
+       if (mf_a) s = s * mf_a->get_qdim() / mf_a->nb_dof();
+       GMM_ASSERT1(s == Q*Q,
+                   "Bad format Fourier-Robin brick coefficient");
+ 
+       GMM_TRACE2("Fourier-Robin term assembly");
+       gmm::clear(matl[0]);
+       if (mf_a)
+         asm_qu_term(matl[0], mim, mf_u, *mf_a, *A, rg);
+       else
+         asm_homogeneous_qu_term(matl[0], mim, mf_u, *A, rg);
+     }
+ 
+     Fourier_Robin_brick(void) {
+       set_flags("Fourier Robin condition", true /* is linear*/,
+                 true /* is symmetric */, true /* is coercive */,
++<<<<<<< HEAD
++                true /* is real */, true /* is complex */);
++=======
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
++>>>>>>> upstream
+     }
+ 
+   };
+ 
+   size_type add_Fourier_Robin_brick(model &md, const mesh_im &mim,
+                                     const std::string &varname,
+                                     const std::string &dataname,
+                                     size_type region) {
+     pbrick pbr = new Fourier_Robin_brick;
+     model::termlist tl;
+     tl.push_back(model::term_description(varname, varname, true));
+     return md.add_brick(pbr, model::varnamelist(1, varname),
+                         model::varnamelist(1, dataname), tl,
+                         model::mimlist(1, &mim), region);
++<<<<<<< HEAD
++=======
+   }
+ 
+   // ----------------------------------------------------------------------
+   //
+   // Basic nonlinear brick
+   //
+   // ----------------------------------------------------------------------
+       
+ #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
+ 
+   class basic_nonlinear_term : public nonlinear_elem_term {
+ 
+   public:
+     dim_type N;
+     const mesh_fem &mf_u;
+     std::vector<scalar_type> U;
+     scalar_type param;
+     base_small_vector V;
+     base_vector coeff;
+     std::string f, dfdu, varname, paramname;
+     mu::Parser parser;
+     bgeot::multi_index sizes_;
+     int version;
+     
+     template <class VECT> basic_nonlinear_term
+     (const mesh_fem &mf_u_, const VECT &U_, scalar_type param_,
+      const std::string &f_, const std::string &dfdu_,
+      const std::string &varname_, const std::string &paramname_,
+      int version_)
+       : N(mf_u_.linked_mesh().dim()), mf_u(mf_u_), U(mf_u.nb_basic_dof()),
+ 	param(param_), f(f_), dfdu(dfdu_), varname(varname_),
+ 	paramname(paramname_), version(version_) {
+       sizes_.resize(1); sizes_[0] = 1;
+       V.resize(1);
+       mf_u.extend_vector(U_, U);
+ 
+       switch (version) {
+       case 0 : parser.SetExpr(dfdu); break; // tangent matrix
+       case 1 : parser.SetExpr(f); break; // rhs
+       }
+       parser.DefineVar(varname, &V[0]);
+       if (paramname.size()) parser.DefineVar(paramname, &param);
+     }
+ 
+     const bgeot::multi_index &sizes(size_type) const { return sizes_; }
+ 
+     virtual void compute(fem_interpolation_context &ctx,
+ 			 bgeot::base_tensor &t) {
+       size_type cv = ctx.convex_num();
+       t.adjust_sizes(sizes_);
+       coeff.resize(mf_u.nb_basic_dof_of_element(cv));
+       gmm::copy(gmm::sub_vector
+                 (U, gmm::sub_index
+                  (mf_u.ind_basic_dof_of_element(cv))), coeff);
+       ctx.pf()->interpolation(ctx, coeff, V, 1);
+ 
+       try {
+ 	t[0] = scalar_type(parser.Eval());
+       } catch (mu::Parser::exception_type &e) {
+ 	std::cerr << "Message  : " << e.GetMsg()   << std::endl;
+ 	std::cerr << "Formula  : " << e.GetExpr()  << std::endl;
+ 	std::cerr << "Token    : " << e.GetToken() << std::endl;
+ 	std::cerr << "Position : " << e.GetPos()   << std::endl;
+ 	std::cerr << "Errc     : " << e.GetCode()  << std::endl;
+ 	GMM_ASSERT1(false, "error in the expressions");
+       }
+     }
+ 
+   };
+ 
+   template<typename MAT, typename VECT>
+   void asm_basic_nonlinear_tangent_matrix
+   (const MAT &K, const mesh_im &mim, const mesh_fem &mf_u, const VECT &U,
+    const std::string &f, const std::string &dfdu, const std::string &varname,
+    const mesh_region &rg = mesh_region::all_convexes(),
+    scalar_type param = 0., const std::string &paramname = std::string()) {
+ 
+     basic_nonlinear_term nterm(mf_u, U, param, f, dfdu, 
+ 			       varname, paramname, 0);
  
-   size_type add_Helmholtz_brick(model &md, const mesh_im &mim,
-                                 const std::string &varname,
-                                 const std::string &dataname,
-                                 size_type region) {
-     pbrick pbr = new Helmholtz_brick;
-     model::termlist tl;
-     tl.push_back(model::term_description(varname, varname, true));
-     return md.add_brick(pbr, model::varnamelist(1, varname),
-                         model::varnamelist(1, dataname), tl,
-                         model::mimlist(1, &mim), region);
+     generic_assembly assem;
+     assem.set("M(#1,#1)+=sym(comp(NonLin(#1).Base(#1).Base(#1))(i,:,:))");
+     assem.push_mi(mim);
+     assem.push_mf(mf_u);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_mat(const_cast<MAT &>(K));
+     assem.assembly(rg);
    }
  
+   template<typename VECT>
+   void asm_basic_nonlinear_rhs
+   (const VECT &V, const mesh_im &mim, const mesh_fem &mf_u, const VECT &U,
+    const std::string &f, const std::string &dfdu, const std::string &varname,
+    const mesh_region &rg = mesh_region::all_convexes(),
+    scalar_type param = 0., const std::string &paramname = std::string()) {
+ 
+     basic_nonlinear_term nterm(mf_u, U, param, f, dfdu,
+ 			       varname, paramname, 1);
  
+     generic_assembly assem;
+     assem.set("V(#1)+=comp(NonLin(#1).Base(#1))(i,:)");
+     assem.push_mi(mim);
+     assem.push_mf(mf_u);
+     assem.push_nonlinear_term(&nterm);
+     assem.push_vec(const_cast<VECT &>(V));
+     assem.assembly(rg);
++>>>>>>> upstream
+   }
  
-   // ----------------------------------------------------------------------
-   //
-   // Fourier-Robin brick
-   //
-   // ----------------------------------------------------------------------
+ #endif
  
-   struct Fourier_Robin_brick : public virtual_brick {
+   struct basic_nonlinear_brick : public virtual_brick {
  
-     virtual void asm_real_tangent_terms(const model &md, size_type,
+     std::string f, dfdu;
+     
+     virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
                                          const model::varnamelist &vl,
                                          const model::varnamelist &dl,
                                          const model::mimlist &mims,
                                          model::real_matlist &matl,
-                                         model::real_veclist &,
+                                         model::real_veclist &vecl,
                                          model::real_veclist &,
                                          size_type region,
-                                         build_version) const {
-       GMM_ASSERT1(matl.size() == 1,
-                   "Fourier-Robin brick has one and only one term");
+                                         build_version version) const {
        GMM_ASSERT1(mims.size() == 1,
-                   "Fourier-Robin brick need one and only one mesh_im");
-       GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
-                   "Wrong number of variables for Fourier-Robin brick");
+ 		  "basic nonlinear brick needs a single mesh_im");
+       GMM_ASSERT1(vl.size() == 1,
+ 		  "basic nonlinear brick needs a single variable");
+       GMM_ASSERT1(dl.size() <= 1,
+ 		  "wrong number of data for basic nonlinear brick");
+       GMM_ASSERT1(matl.size() == 1,  "wrong number of terms for basic "
+ 		  "nonlinear brick");
+ 
+       const model_real_plain_vector &u = md.real_variable(vl[0]);
+       const mesh_fem &mf_u = *(md.pmesh_fem_of_variable(vl[0]));
+       size_type Q = mf_u.get_qdim();
+       GMM_ASSERT1(Q == 1, "basic nonlinear brick is only for scalar field, "
+ 		  "sorry");
+ 
+       const model_real_plain_vector *vparam = 0;
+       if (dl.size()) {
+ 	vparam = &md.real_variable(dl[0]) ;
+ 	size_type sl = gmm::vect_size(*vparam);
+ 	GMM_ASSERT1(sl == 1, "the parameter in basic nonlinear brick "
+ 		    "has to be scalar");
+       }
  
-       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
-       const mesh &m = mf_u.linked_mesh();
-       size_type Q = mf_u.get_qdim(), s = 1;
        const mesh_im &mim = *mims[0];
-       const mesh_fem *mf_a = 0;
        mesh_region rg(region);
-       m.intersect_with_mpi_region(rg);
-       const model_real_plain_vector *A = &(md.real_variable(dl[0]));
-       mf_a = md.pmesh_fem_of_variable(dl[0]);
-       s = gmm::vect_size(*A);
-       if (mf_a) s = s * mf_a->get_qdim() / mf_a->nb_dof();
-       GMM_ASSERT1(s == Q*Q,
-                   "Bad format Fourier-Robin brick coefficient");
+       mf_u.linked_mesh().intersect_with_mpi_region(rg);
  
-       GMM_TRACE2("Fourier-Robin term assembly");
-       gmm::clear(matl[0]);
-       if (mf_a)
-         asm_qu_term(matl[0], mim, mf_u, *mf_a, *A, rg);
-       else
-         asm_homogeneous_qu_term(matl[0], mim, mf_u, *A, rg);
-     }
+ #if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
  
-     virtual void asm_complex_tangent_terms(const model &md, size_type,
-                                            const model::varnamelist &vl,
-                                            const model::varnamelist &dl,
-                                            const model::mimlist &mims,
-                                            model::complex_matlist &matl,
-                                            model::complex_veclist &,
-                                            model::complex_veclist &,
-                                            size_type region,
-                                            build_version) const {
-       GMM_ASSERT1(matl.size() == 1,
-                   "Fourier-Robin brick has one and only one term");
-       GMM_ASSERT1(mims.size() == 1,
-                   "Fourier-Robin brick need one and only one mesh_im");
-       GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
-                   "Wrong number of variables for Fourier-Robin brick");
+       if (version & model::BUILD_MATRIX) {
+ 	gmm::clear(matl[0]);
+ 	GMM_TRACE2("basic nonlinear stiffness matrix assembly");
+ 	if (dl.size())
+ 	  asm_basic_nonlinear_tangent_matrix(matl[0], mim, mf_u, u, f, dfdu,
+ 					     vl[0], rg, (*vparam)[0], dl[0]);
+ 	else
+ 	  asm_basic_nonlinear_tangent_matrix(matl[0], mim, mf_u, u,
+ 					     f, dfdu, vl[0], rg);
+       }
  
-       const mesh_fem &mf_u = md.mesh_fem_of_variable(vl[0]);
-       const mesh &m = mf_u.linked_mesh();
-       size_type Q = mf_u.get_qdim(), s = 1;
-       const mesh_im &mim = *mims[0];
-       const mesh_fem *mf_a = 0;
-       mesh_region rg(region);
-       m.intersect_with_mpi_region(rg);
-       const model_complex_plain_vector *A = &(md.complex_variable(dl[0]));
-       mf_a = md.pmesh_fem_of_variable(dl[0]);
-       s = gmm::vect_size(*A);
-       if (mf_a) s = s * mf_a->get_qdim() / mf_a->nb_dof();
-       GMM_ASSERT1(s == Q*Q,
-                   "Bad format Fourier-Robin brick coefficient");
+       if (version & model::BUILD_RHS) {
+ 	if (dl.size())
+ 	  asm_basic_nonlinear_rhs(vecl[0], mim, mf_u, u,
+ 				  f, dfdu, vl[0], rg, (*vparam)[0], dl[0]);
+ 	else
+ 	  asm_basic_nonlinear_rhs(vecl[0], mim, mf_u, u, f, dfdu, vl[0], rg);
+ 	gmm::scale(vecl[0], scalar_type(-1));
+       }
+       
+ #else
  
-       GMM_TRACE2("Fourier-Robin term assembly");
-       gmm::clear(matl[0]);
-       if (mf_a)
-         asm_qu_term(matl[0], mim, mf_u, *mf_a, *A, rg);
-       else
-         asm_homogeneous_qu_term(matl[0], mim, mf_u, *A, rg);
-     }
+     GMM_ASSERT1(false, "Muparser is not installed, "
+                     "you cannot use basic nonlinear brick");
  
-     Fourier_Robin_brick(void) {
-       set_flags("Fourier Robin condition", true /* is linear*/,
-                 true /* is symmetric */, true /* is coercive */,
-                 true /* is real */, true /* is complex */);
+ #endif
      }
  
+     basic_nonlinear_brick(const std::string &f_, const std::string &dfdu_)
+       : f(f_), dfdu(dfdu_)
+     { set_flags("basic nonlinear brick", false /* is linear*/,
+ 		true /* is symmetric */, false /* is coercive */,
+ 		true /* is real */, false /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
+     }
+     
    };
  
-   size_type add_Fourier_Robin_brick(model &md, const mesh_im &mim,
-                                     const std::string &varname,
-                                     const std::string &dataname,
-                                     size_type region) {
-     pbrick pbr = new Fourier_Robin_brick;
+   size_type add_basic_nonlinear_brick
+   (model &md, const mesh_im &mim, const std::string &varname,
+    const std::string &f, const std::string &dfdu, size_type region,
+    const std::string &dataname) {
+     pbrick pbr = new basic_nonlinear_brick(f, dfdu);
      model::termlist tl;
      tl.push_back(model::term_description(varname, varname, true));
-     return md.add_brick(pbr, model::varnamelist(1, varname),
-                         model::varnamelist(1, dataname), tl,
-                         model::mimlist(1, &mim), region);
+     model::varnamelist vl(1, varname);
+     model::varnamelist dl;
+     if (dataname.size()) dl.push_back(dataname);
+     return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
    }
- 
+     
    // ----------------------------------------------------------------------
    //
 +  // Basic nonlinear brick
 +  //
 +  // ----------------------------------------------------------------------
 +      
 +#if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
 +
 +  class basic_nonlinear_term : public nonlinear_elem_term {
 +
 +  public:
 +    dim_type N;
 +    const mesh_fem &mf_u;
 +    std::vector<scalar_type> U;
 +    scalar_type param;
 +    base_small_vector V;
 +    base_vector coeff;
 +    std::string f, dfdu, varname, paramname;
 +    mu::Parser parser;
 +    bgeot::multi_index sizes_;
 +    int version;
 +    
 +    template <class VECT> basic_nonlinear_term
 +    (const mesh_fem &mf_u_, const VECT &U_, scalar_type param_,
 +     const std::string &f_, const std::string &dfdu_,
 +     const std::string &varname_, const std::string &paramname_,
 +     int version_)
 +      : N(mf_u_.linked_mesh().dim()), mf_u(mf_u_), U(mf_u.nb_basic_dof()),
 +	param(param_), f(f_), dfdu(dfdu_), varname(varname_),
 +	paramname(paramname_), version(version_) {
 +      sizes_.resize(1); sizes_[0] = 1;
 +      V.resize(1);
 +      mf_u.extend_vector(U_, U);
 +
 +      switch (version) {
 +      case 0 : parser.SetExpr(dfdu); break; // tangent matrix
 +      case 1 : parser.SetExpr(f); break; // rhs
 +      }
 +      parser.DefineVar(varname, &V[0]);
 +      if (paramname.size()) parser.DefineVar(paramname, &param);
 +    }
 +
 +    const bgeot::multi_index &sizes() const { return sizes_; }
 +
 +    virtual void compute(fem_interpolation_context &ctx,
 +			 bgeot::base_tensor &t) {
 +      size_type cv = ctx.convex_num();
 +      t.adjust_sizes(sizes_);
 +      coeff.resize(mf_u.nb_basic_dof_of_element(cv));
 +      gmm::copy(gmm::sub_vector
 +                (U, gmm::sub_index
 +                 (mf_u.ind_basic_dof_of_element(cv))), coeff);
 +      ctx.pf()->interpolation(ctx, coeff, V, 1);
 +
 +      try {
 +	t[0] = scalar_type(parser.Eval());
 +      } catch (mu::Parser::exception_type &e) {
 +	std::cerr << "Message  : " << e.GetMsg()   << std::endl;
 +	std::cerr << "Formula  : " << e.GetExpr()  << std::endl;
 +	std::cerr << "Token    : " << e.GetToken() << std::endl;
 +	std::cerr << "Position : " << e.GetPos()   << std::endl;
 +	std::cerr << "Errc     : " << e.GetCode()  << std::endl;
 +	GMM_ASSERT1(false, "error in the expressions");
 +      }
 +    }
 +
 +  };
 +
 +  template<typename MAT, typename VECT>
 +  void asm_basic_nonlinear_tangent_matrix
 +  (const MAT &K, const mesh_im &mim, const mesh_fem &mf_u, const VECT &U,
 +   const std::string &f, const std::string &dfdu, const std::string &varname,
 +   const mesh_region &rg = mesh_region::all_convexes(),
 +   scalar_type param = 0., const std::string &paramname = std::string()) {
 +
 +    basic_nonlinear_term nterm(mf_u, U, param, f, dfdu, 
 +			       varname, paramname, 0);
 +
 +    generic_assembly assem;
 +    assem.set("M(#1,#1)+=sym(comp(NonLin(#1).Base(#1).Base(#1))(i,:,:))");
 +    assem.push_mi(mim);
 +    assem.push_mf(mf_u);
 +    assem.push_nonlinear_term(&nterm);
 +    assem.push_mat(const_cast<MAT &>(K));
 +    assem.assembly(rg);
 +  }
 +
 +  template<typename VECT>
 +  void asm_basic_nonlinear_rhs
 +  (const VECT &V, const mesh_im &mim, const mesh_fem &mf_u, const VECT &U,
 +   const std::string &f, const std::string &dfdu, const std::string &varname,
 +   const mesh_region &rg = mesh_region::all_convexes(),
 +   scalar_type param = 0., const std::string &paramname = std::string()) {
 +
 +    basic_nonlinear_term nterm(mf_u, U, param, f, dfdu,
 +			       varname, paramname, 1);
 +
 +    generic_assembly assem;
 +    assem.set("V(#1)+=comp(NonLin(#1).Base(#1))(i,:)");
 +    assem.push_mi(mim);
 +    assem.push_mf(mf_u);
 +    assem.push_nonlinear_term(&nterm);
 +    assem.push_vec(const_cast<VECT &>(V));
 +    assem.assembly(rg);
 +  }
 +
 +#endif
 +
 +  struct basic_nonlinear_brick : public virtual_brick {
 +
 +    std::string f, dfdu;
 +    
 +    virtual void asm_real_tangent_terms(const model &md, size_type /* ib */,
 +                                        const model::varnamelist &vl,
 +                                        const model::varnamelist &dl,
 +                                        const model::mimlist &mims,
 +                                        model::real_matlist &matl,
 +                                        model::real_veclist &vecl,
 +                                        model::real_veclist &,
 +                                        size_type region,
 +                                        build_version version) const {
 +      GMM_ASSERT1(mims.size() == 1,
 +		  "basic nonlinear brick needs a single mesh_im");
 +      GMM_ASSERT1(vl.size() == 1,
 +		  "basic nonlinear brick needs a single variable");
 +      GMM_ASSERT1(dl.size() <= 1,
 +		  "wrong number of data for basic nonlinear brick");
 +      GMM_ASSERT1(matl.size() == 1,  "wrong number of terms for basic "
 +		  "nonlinear brick");
 +
 +      const model_real_plain_vector &u = md.real_variable(vl[0]);
 +      const mesh_fem &mf_u = *(md.pmesh_fem_of_variable(vl[0]));
 +      size_type Q = mf_u.get_qdim();
 +      GMM_ASSERT1(Q == 1, "basic nonlinear brick is only for scalar field, "
 +		  "sorry");
 +
 +      const model_real_plain_vector *vparam = 0;
 +      if (dl.size()) {
 +	vparam = &md.real_variable(dl[0]) ;
 +	size_type sl = gmm::vect_size(*vparam);
 +	GMM_ASSERT1(sl == 1, "the parameter in basic nonlinear brick "
 +		    "has to be scalar");
 +      }
 +
 +      const mesh_im &mim = *mims[0];
 +      mesh_region rg(region);
 +      mf_u.linked_mesh().intersect_with_mpi_region(rg);
 +
 +#if GETFEM_HAVE_MUPARSER_MUPARSER_H || GETFEM_HAVE_MUPARSER_H
 +
 +      if (version & model::BUILD_MATRIX) {
 +	gmm::clear(matl[0]);
 +	GMM_TRACE2("basic nonlinear stiffness matrix assembly");
 +	if (dl.size())
 +	  asm_basic_nonlinear_tangent_matrix(matl[0], mim, mf_u, u, f, dfdu,
 +					     vl[0], rg, (*vparam)[0], dl[0]);
 +	else
 +	  asm_basic_nonlinear_tangent_matrix(matl[0], mim, mf_u, u,
 +					     f, dfdu, vl[0], rg);
 +      }
 +
 +      if (version & model::BUILD_RHS) {
 +	if (dl.size())
 +	  asm_basic_nonlinear_rhs(vecl[0], mim, mf_u, u,
 +				  f, dfdu, vl[0], rg, (*vparam)[0], dl[0]);
 +	else
 +	  asm_basic_nonlinear_rhs(vecl[0], mim, mf_u, u, f, dfdu, vl[0], rg);
 +	gmm::scale(vecl[0], scalar_type(-1));
 +      }
 +      
 +#else
 +
 +    GMM_ASSERT1(false, "Muparser is not installed, "
 +                    "you cannot use basic nonlinear brick");
 +
 +#endif
 +    }
 +
 +    basic_nonlinear_brick(const std::string &f_, const std::string &dfdu_)
 +      : f(f_), dfdu(dfdu_)
 +    { set_flags("basic nonlinear brick", false /* is linear*/,
 +		true /* is symmetric */, false /* is coercive */,
 +		true /* is real */, false /* is complex */);
 +    }
 +    
 +  };
 +
 +  size_type add_basic_nonlinear_brick
 +  (model &md, const mesh_im &mim, const std::string &varname,
 +   const std::string &f, const std::string &dfdu, size_type region,
 +   const std::string &dataname) {
 +    pbrick pbr = new basic_nonlinear_brick(f, dfdu);
 +    model::termlist tl;
 +    tl.push_back(model::term_description(varname, varname, true));
 +    model::varnamelist vl(1, varname);
 +    model::varnamelist dl;
 +    if (dataname.size()) dl.push_back(dataname);
 +    return md.add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
 +  }
 +    
 +  // ----------------------------------------------------------------------
 +  //
    // Constraint brick
    //
    // ----------------------------------------------------------------------
@@@ -3006,7 -4677,8 +5611,12 @@@
                            : "Constraint with multipliers brick",
                  true /* is linear*/,
                  true /* is symmetric */, penalized /* is coercive */,
++<<<<<<< HEAD
 +                true /* is real */, true /* is complex */);
++=======
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
++>>>>>>> upstream
      }
  
    };
@@@ -3125,7 -4797,8 +5735,12 @@@
                  true /* is linear*/,
                  symmetric_ /* is symmetric */, coercive_ /* is coercive */,
                  true /* is real */, true /* is complex */,
++<<<<<<< HEAD
 +                true /* is to be computed each time */);
++=======
+                 true /* is to be computed each time */,
+ 		false /* has a Neumann term */);
++>>>>>>> upstream
      }
    };
  
@@@ -3188,7 -4861,8 +5803,12 @@@
                  true /* is linear*/,
                  true /* is symmetric */, true /* is coercive */,
                  true /* is real */, true /* is complex */,
++<<<<<<< HEAD
 +                true /* is to be computed each time */);
++=======
+                 true /* is to be computed each time */,
+ 		false /* has a Neumann term */);
++>>>>>>> upstream
      }
  
    };
@@@ -3270,6 -5074,11 +6020,14 @@@
          else
            asm_stiffness_matrix_for_homogeneous_linear_elasticity
              (matl[0], mim, mf_u, *lambda, *mu, rg);
++<<<<<<< HEAD
++=======
+ 
+ 
+ 	pNeumann_elem_term pNt = new iso_lin_elasticity_Neumann_elem_term
+ 	  (mf_lambda, lambda, mf_mu, mu);
+ 	md.add_Neumann_term(pNt, vl[0], ib);
++>>>>>>> upstream
        }
  
        if  (dl.size() == 3) { // Pre-constraints given by an "initial"
@@@ -3333,9 -5142,9 +6091,15 @@@
      size_type sm = gmm::vect_size(*mu);
      if (mf_mu) sm = sm * mf_mu->get_qdim() / mf_mu->nb_dof();
  
++<<<<<<< HEAD
 +    GMM_ASSERT1(sl == 1 && sm == 1, "Bad format for Lam� coefficients");
 +    GMM_ASSERT1(mf_lambda == mf_mu,
 +                "The two Lam� coefficients should be described on the same "
++=======
+     GMM_ASSERT1(sl == 1 && sm == 1, "Bad format for Lam� coefficients");
+     GMM_ASSERT1(mf_lambda == mf_mu,
+                 "The two Lam� coefficients should be described on the same "
++>>>>>>> upstream
                  "finite element method.");
  
      if (mf_lambda) {
@@@ -3362,9 -5171,104 +6126,110 @@@
    //
    // ----------------------------------------------------------------------
  
++<<<<<<< HEAD
 +  struct linear_incompressibility_brick : public virtual_brick {
 +
 +    virtual void asm_real_tangent_terms(const model &md, size_type,
++=======
+   struct lin_incomp_Neumann_elem_term : public Neumann_elem_term {
+ 
+     const gmm::uint64_type &var_vnum; 
+     const mesh_fem *mf_p;
+     const model_real_plain_vector *org_P;
+     mutable model_real_plain_vector P;
+     mutable gmm::uint64_type vnum;
+     
+     mutable fem_interpolation_context ctx_p;
+     mutable base_vector coeff, val;
+     mutable base_matrix G;
+    
+     void compute_Neumann_term
+     (int version, const mesh_fem &mfvar,
+      const model_real_plain_vector &/* var */,
+      fem_interpolation_context& ctx, base_small_vector &n,
+      base_tensor &output, size_type auxilliary_ind = 0) const {
+ 
+       if (version == 3) return;  // No contribution because the term is linear
+       if (version == 2 && auxilliary_ind == 0) return;
+ 
+       dim_type qdim = mfvar.linked_mesh().dim();
+       size_type cv = ctx.convex_num();
+    
+       if (vnum != var_vnum || !(ctx_p.have_pf()) || ctx_p.convex_num() != cv
+ 	  || (ctx_p.have_pfp() != ctx.have_pfp())
+ 	  || (ctx_p.have_pfp()
+ 	      && (&(ctx.pfp()->get_point_tab())
+ 		  != &(ctx_p.pfp()->get_point_tab())))) {
+ 
+ 	if (vnum != var_vnum) {
+ 	  gmm::resize(P, mf_p->nb_basic_dof());
+           mf_p->extend_vector(*org_P, P);
+           vnum = var_vnum;
+ 	}
+ 	
+ 	bgeot::vectors_to_base_matrix
+ 	  (G, mf_p->linked_mesh().points_of_convex(cv));
+ 	
+ 	if (ctx.have_pfp()) {
+           pfem_precomp pfp = fem_precomp(mf_p->fem_of_element(cv),
+                                          &(ctx.pfp()->get_point_tab()), 0);
+ 	  ctx_p = fem_interpolation_context
+ 	    (mf_p->linked_mesh().trans_of_convex(cv), pfp, ctx.ii(),
+ 	     G, cv, ctx.face_num());
+         } else
+ 	  ctx_p = fem_interpolation_context
+ 	    (mf_p->linked_mesh().trans_of_convex(cv),
+ 	     mf_p->fem_of_element(cv), ctx.xref(), G, cv, ctx.face_num());
+       } else {
+ 	if (ctx_p.have_pfp()) ctx_p.set_ii(ctx.ii());
+ 	else ctx_p.set_xref(ctx.xref());
+        
+       }
+ 
+       switch (version) {
+       case 1:
+         coeff.resize(mf_p->nb_basic_dof_of_element(cv));
+ 	gmm::copy(gmm::sub_vector(P, gmm::sub_index
+                                  (mf_p->ind_basic_dof_of_element(cv))), coeff);
+ 	ctx_p.pf()->interpolation(ctx_p, coeff, val, 1);
+        
+         for (size_type k = 0; k < qdim; ++k) output[k] -= val[0] * n[k];
+ 	break;
+       case 2:
+ 	{
+ 	  base_tensor t;
+ 	  size_type ndof = ctx_p.pf()->nb_dof(cv);
+ 	  ctx_p.pf()->real_base_value(ctx_p, t);
+ 
+           for (size_type i = 0; i < ndof; ++i)
+ 	    for (size_type k = 0; k < qdim; ++k)
+               output(i, k) -= t[i]*n[k];
+ 	}
+ 	break;
+       }
+ 
+     }
+ 
+     lin_incomp_Neumann_elem_term
+     (const gmm::uint64_type &var_vnum_, const mesh_fem *mf_p_, 
+      const model_real_plain_vector *P_,
+      const std::string &auxvarname)
+       : var_vnum(var_vnum_), mf_p(mf_p_), org_P(P_)  {
+       auxilliary_variables.push_back(auxvarname);
+       gmm::resize(P, mf_p->nb_basic_dof());
+       mf_p->extend_vector(*P_, P);
+       vnum = var_vnum;
+       gmm::resize(val, 1);
+     }
+ 
+   };
+ 
+ 
+ 
+   struct linear_incompressibility_brick : public virtual_brick {
+ 
+     virtual void asm_real_tangent_terms(const model &md, size_type ib,
++>>>>>>> upstream
                                          const model::varnamelist &vl,
                                          const model::varnamelist &dl,
                                          const model::mimlist &mims,
@@@ -3569,7 -5479,8 +6440,12 @@@
      mass_brick(void) {
        set_flags("Mass brick", true /* is linear*/,
                  true /* is symmetric */, true /* is coercive */,
++<<<<<<< HEAD
 +                true /* is real */, true /* is complex */);
++=======
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
++>>>>>>> upstream
      }
  
    };
@@@ -3722,7 -5633,8 +6598,12 @@@
      basic_d_on_dt_brick(void) {
        set_flags("Basic d/dt brick", true /* is linear*/,
                  true /* is symmetric */, true /* is coercive */,
++<<<<<<< HEAD
 +                true /* is real */, true /* is complex */);
++=======
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
++>>>>>>> upstream
      }
  
    };
@@@ -3890,7 -5802,8 +6771,12 @@@
      basic_d2_on_dt2_brick(void) {
        set_flags("Basic d2/dt2 brick", true /* is linear*/,
                  true /* is symmetric */, true /* is coercive */,
++<<<<<<< HEAD
 +                true /* is real */, true /* is complex */);
++=======
+                 true /* is real */, true /* is complex */,
+ 		false /* compute each time */, false /* has a Neumann term */);
++>>>>>>> upstream
      }
  
    };
diff --cc src/getfem_nonlinear_elasticity.cc
index 3b26f96,2bdc8fe..ed1d66e
--- a/src/getfem_nonlinear_elasticity.cc
+++ b/src/getfem_nonlinear_elasticity.cc
@@@ -511,8 -511,10 +511,15 @@@ namespace getfem 
    }
  
    scalar_type Mooney_Rivlin_hyperelastic_law::strain_energy
++<<<<<<< HEAD
 +  (const base_matrix &E, const base_vector &params, scalar_type) const {
 +    scalar_type C1 = params[0], C2 = params[1];
++=======
+   (const base_matrix &E, const base_vector &params,
+    scalar_type /* det_trans*/) const {
+ // shouldn't negative det_trans be handled here???
+ //    if (compressible && det_trans <= scalar_type(0)) return 1e200;
++>>>>>>> upstream
      size_type N = gmm::mat_nrows(E);
      GMM_ASSERT1(N == 3, "Mooney Rivlin hyperelastic law only defined "
  		"on dimension 3, sorry");
@@@ -526,8 -539,7 +544,12 @@@
  
    void Mooney_Rivlin_hyperelastic_law::sigma
    (const base_matrix &E, base_matrix &result,
++<<<<<<< HEAD
 +   const base_vector &params, scalar_type) const {
 +    scalar_type C1 = params[0], C2 = params[1];
++=======
+    const base_vector &params, scalar_type /*det_trans*/) const {
++>>>>>>> upstream
      size_type N = gmm::mat_nrows(E);
      GMM_ASSERT1(N == 3, "Mooney Rivlin hyperelastic law only defined "
  		"on dimension 3, sorry");
@@@ -544,7 -568,6 +578,10 @@@
    void Mooney_Rivlin_hyperelastic_law::grad_sigma
    (const base_matrix &E, base_tensor &result,
     const base_vector &params, scalar_type) const {
++<<<<<<< HEAD
 +    scalar_type C1 = params[0], C2 = params[1];
++=======
++>>>>>>> upstream
      size_type N = gmm::mat_nrows(E);
      GMM_ASSERT1(N == 3, "Mooney Rivlin hyperelastic law only defined "
  		"on dimension 3, sorry");
@@@ -583,103 -632,103 +646,219 @@@
      compute_invariants ci(C);
  
      return pow(a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
+                + c*ci.i2() / ci.i3() + d, n);
+   }
+ 
+   void generalized_Blatz_Ko_hyperelastic_law::sigma
+   (const base_matrix &E, base_matrix &result,
+    const base_vector &params, scalar_type det_trans) const {
+     scalar_type a = params[0], b = params[1], c = params[2], d = params[3];
+     scalar_type n = params[4];
+     size_type N = gmm::mat_nrows(E);
+     GMM_ASSERT1(N == 3, "Generalized Blatz Ko hyperelastic law only defined "
+ 		"on dimension 3, sorry");
+     base_matrix C = E;
+     gmm::scale(C, scalar_type(2));
+     gmm::add(gmm::identity_matrix(), C);
+     compute_invariants ci(C);
+ 
+     scalar_type z = a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
+       + c*ci.i2() / ci.i3() + d;
+     scalar_type nz = n * pow(z, n-1.);
+     scalar_type di1 = nz * a;
+     scalar_type di2 = nz * c / ci.i3();
+     scalar_type di3 = nz *
+       (b / (2. * sqrt(gmm::abs(ci.i3()))) - c * ci.i2() / gmm::sqr(ci.i3()));
+ 
+     gmm::copy(gmm::scaled(ci.grad_i1(), di1 * 2.0), result);
+     gmm::add(gmm::scaled(ci.grad_i2(), di2 * 2.0), result);
+     gmm::add(gmm::scaled(ci.grad_i3(), di3 * 2.0), result);
+     if (det_trans <= scalar_type(0))
+       gmm::add(gmm::scaled(C, 1e200), result);
+ 
+   }
+ 
+   void generalized_Blatz_Ko_hyperelastic_law::grad_sigma
+   (const base_matrix &E, base_tensor &result,
+    const base_vector &params, scalar_type) const {
+     scalar_type a = params[0], b = params[1], c = params[2], d = params[3];
+     scalar_type n = params[4];
+     size_type N = gmm::mat_nrows(E);
+     GMM_ASSERT1(N == 3, "Generalized Blatz Ko hyperelastic law only defined "
+ 		"on dimension 3, sorry");
+     base_matrix C = E;
+     gmm::scale(C, scalar_type(2));
+     gmm::add(gmm::identity_matrix(), C);
+     compute_invariants ci(C);
+ 
+ 
+     scalar_type z = a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
+       + c*ci.i2() / ci.i3() + d;
+     scalar_type nz = n * pow(z, n-1.);
+     scalar_type di1 = nz * a;
+     scalar_type di2 = nz * c / ci.i3();
+     scalar_type y = (b / (2. * sqrt(gmm::abs(ci.i3()))) - c * ci.i2() / gmm::sqr(ci.i3()));
+     scalar_type di3 = nz * y;
+ 
+     gmm::copy(gmm::scaled(ci.sym_grad_grad_i1().as_vector(),
+  			  scalar_type(4)*di1), result.as_vector());
+     gmm::add(gmm::scaled(ci.sym_grad_grad_i2().as_vector(),
+ 			 scalar_type(4)*di2), result.as_vector());
+     gmm::add(gmm::scaled(ci.sym_grad_grad_i3().as_vector(),
+ 			 scalar_type(4)*di3), result.as_vector());
+ 
+     scalar_type nnz = n * (n-1.) * pow(z, n-2.);
+     base_matrix A(3, 3); // second derivatives of W with respect to invariants
+     A(0, 0) = nnz * a * a;
+     A(1, 0) = A(0, 1) = nnz * a * c / ci.i3();
+     A(2, 0) = A(0, 2) = nnz * a * y;
+     A(1, 1) = nnz * c * c / gmm::sqr(ci.i3());
+     A(2, 1) = A(1, 2) = nnz * y * c / ci.i3() - nz * c / gmm::sqr(ci.i3());
+     A(2, 2) = nnz * y * y + nz * (2. * c * ci.i2() / pow(ci.i3(), 3.) - b / (4. * pow(ci.i3(), 1.5)));
+ 
+     typedef const base_matrix * pointer_base_matrix__;
+     pointer_base_matrix__ di[3];
+     di[0] = &(ci.grad_i1()); 
+     di[1] = &(ci.grad_i2()); 
+     di[2] = &(ci.grad_i3());
+ 
+     for (size_type j = 0; j < N; ++j)
+       for (size_type k = 0; k < N; ++k) {
+ 	for (size_type l1 = 0; l1 < N; ++l1)
+ 	  for (size_type l2 = 0; l2 < N; ++l2)
+ 	    for (size_type l3 = 0; l3 < N; ++l3)
+ 	      for (size_type l4 = 0; l4 < N; ++l4)
+ 		result(l1, l2, l3, l4)
+ 		  += 4. * A(j, k) * (*di[j])(l1, l2) * (*di[k])(l3, l4);
+       }
+ 
+ //     GMM_ASSERT1(check_symmetry(result) == 7,
+ // 		"Fourth order tensor not symmetric : " << result);
+   }
+ 
+   generalized_Blatz_Ko_hyperelastic_law::generalized_Blatz_Ko_hyperelastic_law(void) {
+     nb_params_ = 5;
+     base_vector V(5);
+     V[0] = 1.0;  V[1] = 1.0, V[2] = 1.5; V[3] = -0.5; V[4] = 1.5;
+   }
+ 
+ 
++<<<<<<< HEAD
++
++
++  scalar_type generalized_Blatz_Ko_hyperelastic_law::strain_energy
++  (const base_matrix &E, const base_vector &params, scalar_type det_trans) const {
++    if (det_trans <= scalar_type(0)) return 1e200;
++    scalar_type a = params[0], b = params[1], c = params[2], d = params[3];
++    scalar_type n = params[4];
++    size_type N = gmm::mat_nrows(E);
++    GMM_ASSERT1(N == 3, "Generalized Blatz Ko hyperelastic law only defined "
++		"on dimension 3, sorry");
++    base_matrix C = E;
++    gmm::scale(C, scalar_type(2));
++    gmm::add(gmm::identity_matrix(), C);
++    compute_invariants ci(C);
++
++    return pow(a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
 +	       + c*ci.i2() / ci.i3() + d, n);
 +  }
 +
 +  void generalized_Blatz_Ko_hyperelastic_law::sigma
 +  (const base_matrix &E, base_matrix &result,
 +   const base_vector &params, scalar_type det_trans) const {
 +    scalar_type a = params[0], b = params[1], c = params[2], d = params[3];
 +    scalar_type n = params[4];
 +    size_type N = gmm::mat_nrows(E);
 +    GMM_ASSERT1(N == 3, "Generalized Blatz Ko hyperelastic law only defined "
 +		"on dimension 3, sorry");
 +    base_matrix C = E;
 +    gmm::scale(C, scalar_type(2));
 +    gmm::add(gmm::identity_matrix(), C);
 +    compute_invariants ci(C);
 +
 +    scalar_type z = a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
 +      + c*ci.i2() / ci.i3() + d;
 +    scalar_type nz = n * pow(z, n-1.);
 +    scalar_type di1 = nz * a;
 +    scalar_type di2 = nz * c / ci.i3();
 +    scalar_type di3 = nz *
 +      (b / (2. * sqrt(gmm::abs(ci.i3()))) - c * ci.i2() / gmm::sqr(ci.i3()));
 +
 +    gmm::copy(gmm::scaled(ci.grad_i1(), di1 * 2.0), result);
 +    gmm::add(gmm::scaled(ci.grad_i2(), di2 * 2.0), result);
 +    gmm::add(gmm::scaled(ci.grad_i3(), di3 * 2.0), result);
 +    if (det_trans <= scalar_type(0))
 +      gmm::add(gmm::scaled(C, 1e200), result);
 +
 +  }
 +
 +  void generalized_Blatz_Ko_hyperelastic_law::grad_sigma
 +  (const base_matrix &E, base_tensor &result,
 +   const base_vector &params, scalar_type) const {
 +    scalar_type a = params[0], b = params[1], c = params[2], d = params[3];
 +    scalar_type n = params[4];
 +    size_type N = gmm::mat_nrows(E);
 +    GMM_ASSERT1(N == 3, "Generalized Blatz Ko hyperelastic law only defined "
 +		"on dimension 3, sorry");
 +    base_matrix C = E;
 +    gmm::scale(C, scalar_type(2));
 +    gmm::add(gmm::identity_matrix(), C);
 +    compute_invariants ci(C);
 +
 +
 +    scalar_type z = a*ci.i1() + b*sqrt(gmm::abs(ci.i3()))
 +      + c*ci.i2() / ci.i3() + d;
 +    scalar_type nz = n * pow(z, n-1.);
 +    scalar_type di1 = nz * a;
 +    scalar_type di2 = nz * c / ci.i3();
 +    scalar_type y = (b / (2. * sqrt(gmm::abs(ci.i3()))) - c * ci.i2() / gmm::sqr(ci.i3()));
 +    scalar_type di3 = nz * y;
 +
 +    gmm::copy(gmm::scaled(ci.sym_grad_grad_i1().as_vector(),
 + 			  scalar_type(4)*di1), result.as_vector());
 +    gmm::add(gmm::scaled(ci.sym_grad_grad_i2().as_vector(),
 +			 scalar_type(4)*di2), result.as_vector());
 +    gmm::add(gmm::scaled(ci.sym_grad_grad_i3().as_vector(),
 +			 scalar_type(4)*di3), result.as_vector());
 +
 +    scalar_type nnz = n * (n-1.) * pow(z, n-2.);
 +    base_matrix A(3, 3); // second derivatives of W with respect to invariants
 +    A(0, 0) = nnz * a * a;
 +    A(1, 0) = A(0, 1) = nnz * a * c / ci.i3();
 +    A(2, 0) = A(0, 2) = nnz * a * y;
 +    A(1, 1) = nnz * c * c / gmm::sqr(ci.i3());
 +    A(2, 1) = A(1, 2) = nnz * y * c / ci.i3() - nz * c / gmm::sqr(ci.i3());
 +    A(2, 2) = nnz * y * y + nz * (2. * c * ci.i2() / pow(ci.i3(), 3.) - b / (4. * pow(ci.i3(), 1.5)));
 +
 +    typedef const base_matrix * pointer_base_matrix__;
 +    pointer_base_matrix__ di[3];
 +    di[0] = &(ci.grad_i1()); 
 +    di[1] = &(ci.grad_i2()); 
 +    di[2] = &(ci.grad_i3());
 +
 +    for (size_type j = 0; j < N; ++j)
 +      for (size_type k = 0; k < N; ++k) {
 +	for (size_type l1 = 0; l1 < N; ++l1)
 +	  for (size_type l2 = 0; l2 < N; ++l2)
 +	    for (size_type l3 = 0; l3 < N; ++l3)
 +	      for (size_type l4 = 0; l4 < N; ++l4)
 +		result(l1, l2, l3, l4)
 +		  += 4. * A(j, k) * (*di[j])(l1, l2) * (*di[k])(l3, l4);
 +      }
 +
 +//     GMM_ASSERT1(check_symmetry(result) == 7,
 +// 		"Fourth order tensor not symmetric : " << result);
 +  }
 +
 +  generalized_Blatz_Ko_hyperelastic_law::generalized_Blatz_Ko_hyperelastic_law(void) {
 +    nb_params_ = 5;
 +    base_vector V(5);
 +    V[0] = 1.0;  V[1] = 1.0, V[2] = 1.5; V[3] = -0.5; V[4] = 1.5;
 +  }
 +
 +
++=======
++>>>>>>> upstream
    scalar_type Ciarlet_Geymonat_hyperelastic_law::strain_energy
    (const base_matrix &E, const base_vector &params, scalar_type det_trans) const {
      if (det_trans <= scalar_type(0)) return 1e200;
diff --cc src/getfem_plasticity.cc
index 376b290,310e4db..90e4824
--- a/src/getfem_plasticity.cc
+++ b/src/getfem_plasticity.cc
@@@ -1,9 -1,9 +1,17 @@@
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2000-2012 Yves Renard
 + 
 + This file is a part of GETFEM++
 + 
++=======
+ 
+  Copyright (C) 2000-2012 Yves Renard
+ 
+  This file is a part of GETFEM++
+ 
++>>>>>>> upstream
   Getfem++  is  free software;  you  can  redistribute  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
@@@ -16,7 -16,7 +24,11 @@@
   You  should  have received a copy of the GNU Lesser General Public License
   along  with  this program;  if not, write to the Free Software Foundation,
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  
diff --cc src/getfem_projected_fem.cc
index 1e0c22d,3fde5be..44cd14c
--- a/src/getfem_projected_fem.cc
+++ b/src/getfem_projected_fem.cc
@@@ -1,9 -1,9 +1,17 @@@
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2012-2012 Yves Renard, Konstantinos Poulios
 + 
 + This file is a part of GETFEM++
 + 
++=======
+ 
+  Copyright (C) 2012-2012 Yves Renard, Konstantinos Poulios
+ 
+  This file is a part of GETFEM++
+ 
++>>>>>>> upstream
   Getfem++  is  free software;  you  can  redistribute  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
@@@ -16,7 -16,7 +24,11 @@@
   You  should  have received a copy of the GNU Lesser General Public License
   along  with  this program;  if not, write to the Free Software Foundation,
   Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  #include "getfem/getfem_projected_fem.h"
@@@ -37,7 -37,7 +49,11 @@@ namespace getfem 
    */
    void projection_on_convex_face
      (const bgeot::pgeometric_trans pgt, const base_matrix &G_cv,
++<<<<<<< HEAD
 +     const short_type fc, const base_node &pt, 
++=======
+      const short_type fc, const base_node &pt,
++>>>>>>> upstream
       base_node &proj_ref) {
  
      size_type N = gmm::mat_nrows(G_cv); // dimension of the target space
@@@ -56,7 -56,7 +72,11 @@@
        gmm::copy(gmm::mat_col(G_cv,ind_pts_fc[i]),gmm::mat_col(G_fc,i));
  
      // Local base on reference face
++<<<<<<< HEAD
 +    base_matrix base_ref_fc(N,P-1);
++=======
+     base_matrix base_ref_fc(P,P-1);
++>>>>>>> upstream
      {
        dref_convex_pt_ct dref_pts_fc = pgt->convex_ref()->dir_points_of_face(fc);
        GMM_ASSERT1( dref_pts_fc.size() == P, "Dimensions mismatch");
@@@ -115,8 -115,8 +135,13 @@@
     *   fc    : the face of the convex to project on
     *   ref_pt: the point in the reference element
     * Output:
++<<<<<<< HEAD
 +   *   normal  : the surface normal in the real element corresponding at
 +   *             the location of ref_pt in the refernce element
++=======
+    *   normal: the surface normal in the real element corresponding at
+    *           the location of ref_pt in the reference element
++>>>>>>> upstream
    */
    void normal_on_convex_face
      (const bgeot::pgeometric_trans pgt, const base_matrix &G_cv,
@@@ -137,7 -137,7 +162,11 @@@
        gmm::copy(gmm::mat_col(G_cv,ind_pts_fc[i]),gmm::mat_col(G_fc,i));
  
      // Local base on reference face
++<<<<<<< HEAD
 +    base_matrix base_ref_fc(N,P-1);
++=======
+     base_matrix base_ref_fc(P,P-1);
++>>>>>>> upstream
      {
        dref_convex_pt_ct dref_pts_fc = pgt->convex_ref()->dir_points_of_face(fc);
        GMM_ASSERT1( dref_pts_fc.size() == P, "Dimensions mismatch");
@@@ -178,7 -178,7 +207,11 @@@
  
      // normalizing
      gmm::scale(normal, 1/gmm::vect_norm2(normal));
++<<<<<<< HEAD
 + 
++=======
+ 
++>>>>>>> upstream
      // ensure that normal points outwards
      base_node cv_center(N), fc_center(N);
      for (size_type i=0; i < nb_pts_cv; i++)
@@@ -191,22 -191,71 +224,87 @@@
        gmm::scale(normal, scalar_type(-1));
    }
  
++<<<<<<< HEAD
 +  void projected_fem::build_kdtree(void) const {
 +    tree.clear();
 +    dal::bit_vector dofs=mf_source.dof_on_region(-1);
 +    dofs.setminus(blocked_dofs);
 +    dim_type qdim=target_dim();
 +    for (size_type dof=0; dof < mf_source.nb_dof(); dof += qdim) {
 +        if (dofs.is_in(dof))
 +            tree.add_point_with_id(mf_source.point_of_basic_dof(dof), dof);
 +    }
++=======
+   /* calculates the normal at a specific point of a convex in a higher
+    * dimension space
+    * Input:
+    *   pgt   : the geometric transformation of the convex
+    *   G_cv  : the nodes of the convex, stored in columns
+    *   ref_pt: the point in the reference element
+    * Output:
+    *   normal: the surface normal in the real element corresponding at
+    *           the location of ref_pt in the reference element
+    *           (or one of the possible normals if the space dimension
+    *           is more than one higher than the convex dimension)
+   */
+   void normal_on_convex
+     (const bgeot::pgeometric_trans pgt, const base_matrix &G_cv,
+      const base_node &ref_pt, base_node &normal) {
+ 
+     size_type N = gmm::mat_nrows(G_cv); // dimension of the target space
+     size_type P = pgt->dim();           // dimension of the reference element space
+ 
+     GMM_ASSERT1( N == 2 || N == 3, "Normal on convexes calculation is supported "
+                                    "only for space dimension equal to 2 or 3.");
+     GMM_ASSERT1( P < N, "Normal on convex is defined only in a space of"
+                         "higher dimension.");
+ 
+     size_type nb_pts = gmm::mat_ncols(G_cv);
+     base_matrix K(N,P);
+     { // calculate K at the final point
+       base_matrix grad_cv(nb_pts, P);
+       pgt->poly_vector_grad(ref_pt, grad_cv);
+       gmm::mult(G_cv, grad_cv, K);
+     }
+ 
+     gmm::resize(normal,N);
+     if (P==1 && N == 2) {
+       normal[0] = -K(1,0);
+       normal[1] = K(0,0);
+     }
+     else if (P==1 && N == 3) {
+       normal[0] = K(2,0)-K(1,0);
+       normal[1] = K(0,0)-K(2,0);
+       normal[2] = K(1,0)-K(0,0);
+     }
+     else if (P==2) {
+       normal[0] = K(1,0)*K(2,1)-K(2,0)*K(1,1);
+       normal[1] = K(2,0)*K(0,1)-K(0,0)*K(2,1);
+       normal[2] = K(0,0)*K(1,1)-K(1,0)*K(0,1);
+     }
+     gmm::scale(normal, 1/gmm::vect_norm2(normal));
+   }
+ 
+   void projected_fem::build_kdtree(void) const {
+     tree.clear();
+     dal::bit_vector dofs=mf_source.basic_dof_on_region(rg_source);
+     dofs.setminus(blocked_dofs);
+     dim_type qdim=target_dim();
+     for (dal::bv_visitor dof(dofs); !dof.finished(); ++dof)
+         if (dof % qdim == 0)
+             tree.add_point_with_id(mf_source.point_of_basic_dof(dof), dof);
++>>>>>>> upstream
    }
  
    bool projected_fem::find_a_projected_point(base_node pt, base_node &ptr_proj,
                                               size_type &cv_proj, short_type &fc_proj) const {
  
      bgeot::index_node_pair ipt;
++<<<<<<< HEAD
 +    //scalar_type dist = 
++=======
+     //scalar_type dist =
++>>>>>>> upstream
      tree.nearest_neighbor(ipt, pt);
  
      size_type cv_sel(-1);
@@@ -233,10 -282,10 +331,17 @@@
        }
        else { // project on convex faces
          mesh_region::face_bitset faces = rg_source.faces_of_convex(cv);
++<<<<<<< HEAD
 +        if (faces.count() > 0) {
 +          bgeot::vectors_to_base_matrix(G, mf_source.linked_mesh().points_of_convex(cv));
 +          // this should rarely be more than one face
 +          for (short_type f = 0; f < faces.size(); ++f) {
++=======
+         if (faces.count() > 0) { // this should rarely be more than one face
+           bgeot::vectors_to_base_matrix(G, mf_source.linked_mesh().points_of_convex(cv));
+           short_type nbf = mf_source.linked_mesh().nb_faces_of_convex(cv);
+           for (short_type f = 0; f < nbf; ++f) {
++>>>>>>> upstream
              if (faces.test(f)) {
                projection_on_convex_face(pgt, G, f, pt, proj_ref);
                scalar_type is_in = pgt->convex_ref()->is_in(proj_ref);
@@@ -300,24 -349,28 +405,44 @@@
                    "You have to use approximated integration to project a fem");
        papprox_integration pai = pim->approx_method();
        bgeot::pgeometric_trans pgt = mim_target.linked_mesh().trans_of_convex(cv);
++<<<<<<< HEAD
++=======
+       bgeot::pgeotrans_precomp pgp =
+         bgeot::geotrans_precomp(pgt, &(pai->integration_points()), 0);
++>>>>>>> upstream
        dal::bit_vector dofs;
        size_type last_cv(-1); // refers to the source mesh
        short_type last_f(-1); // refers to the source mesh
        size_type nb_pts = i.is_face() ? pai->nb_points_on_face(f) : pai->nb_points();
        size_type start_pt = i.is_face() ? pai->ind_first_point_on_face(f) : 0;
        elt_projection_data &e = elements[cv];
++<<<<<<< HEAD
 +      for (size_type k = 0; k < nb_pts; ++k) {
 +        gausspt_projection_data &gppd = e.gausspt[start_pt + k];
 +        /* todo: use a geotrans_interpolation_context */
 +        base_node gpt = pgt->transform(i.is_face() ? pai->point_on_face(f,k) : pai->point(k),
 +                                       mim_target.linked_mesh().points_of_convex(cv));
 +
++=======
+       base_node gpt(N);
+       for (size_type k = 0; k < nb_pts; ++k) {
+         pgp->transform(mim_target.linked_mesh().points_of_convex(cv),
+                        start_pt + k, gpt);
+         gausspt_projection_data &gppd = e.gausspt[start_pt + k];
++>>>>>>> upstream
          gppd.iflags = find_a_projected_point(gpt, gppd.ptref, gppd.cv, gppd.f) ? 1 : 0;
          if (gppd.iflags) {
            // calculate gppd.normal
            const bgeot::pgeometric_trans pgt_source = mf_source.linked_mesh().trans_of_convex(gppd.cv);
            bgeot::vectors_to_base_matrix(G, mf_source.linked_mesh().points_of_convex(gppd.cv));
++<<<<<<< HEAD
 +          normal_on_convex_face(pgt_source, G, gppd.f, gppd.ptref, gppd.normal);
++=======
+           if (gppd.f != short_type(-1))
+             normal_on_convex_face(pgt_source, G, gppd.f, gppd.ptref, gppd.normal);
+           else
+             normal_on_convex(pgt_source, G, gppd.ptref, gppd.normal);
++>>>>>>> upstream
            // calculate gppd.gap
            base_node ppt = pgt_source->transform(gppd.ptref, G);
            gppd.gap = gmm::vect_sp(gpt-ppt, gppd.normal);
@@@ -653,44 -706,54 +778,95 @@@
                                        base_node &normal, scalar_type &gap) const {
      std::map<size_type,elt_projection_data>::iterator eit;
      eit = elements.find(c.convex_num());
++<<<<<<< HEAD
 +    GMM_ASSERT1(eit != elements.end(), "Wrong convex number: " << c.convex_num());
 +    elt_projection_data &e = eit->second;
 +    if (e.nb_dof == 0) { // return undefined normal vector and huge gap
 +        normal = base_node(c.N());
 +        gap = 1e12;
 +        return;
 +    }
 +
 +    std::map<size_type,gausspt_projection_data>::iterator git;
 +    git = e.gausspt.find(c.ii());
 +    if (c.have_pgp() &&
 +        (&c.pgp()->get_point_tab()
 +         == &e.pim->approx_method()->integration_points()) &&
 +        git != e.gausspt.end()) {
 +      gausspt_projection_data &gppd = git->second;
 +      if (gppd.iflags & 1) {
 +        normal = gppd.normal;
 +        gap = gppd.gap;
 +      }
 +      else { // return undefined normal vector and huge gap
 +        normal = base_node(c.N());
 +        gap = 1e12;
 +      }
 +    }
 +    else {
 +      size_type cv;
 +      short_type f;
 +      if (find_a_projected_point(c.xreal(), ptref, cv, f)) {
 +        const bgeot::pgeometric_trans pgt = mf_source.linked_mesh().trans_of_convex(cv);
 +        bgeot::vectors_to_base_matrix(G, mf_source.linked_mesh().points_of_convex(cv));
 +        normal_on_convex_face(pgt, G, f, ptref, normal);
 +        base_node ppt = pgt->transform(ptref, G);
 +        gap = gmm::vect_sp(c.xreal()-ppt, normal);
 +      }
 +      else { // return undefined normal vector and huge gap
 +        normal = base_node(c.N());
 +        gap = 1e12;
 +      }
++=======
+ 
+     if (eit != elements.end()) {
+       elt_projection_data &e = eit->second;
+       if (e.nb_dof == 0) { // return undefined normal vector and huge gap
+         normal = base_node(c.N());
+         gap = 1e12;
+         return;
+       }
+       std::map<size_type,gausspt_projection_data>::iterator git;
+       git = e.gausspt.find(c.ii());
+       if (c.have_pgp() &&
+           (&c.pgp()->get_point_tab()
+            == &e.pim->approx_method()->integration_points()) &&
+           git != e.gausspt.end()) {
+         gausspt_projection_data &gppd = git->second;
+         if (gppd.iflags & 1) {
+           normal = gppd.normal;
+           gap = gppd.gap;
+         }
+         else { // return undefined normal vector and huge gap
+           normal = base_node(c.N());
+           gap = 1e12;
+         }
+         return;
+       }
+     }
+ 
+     // new projection
+     projection_data(c.xreal(), normal, gap);
+   }
+ 
+   void projected_fem::projection_data(const base_node& pt,
+                                       base_node &normal, scalar_type &gap) const {
+     size_type cv;
+     short_type f;
+     if (find_a_projected_point(pt, ptref, cv, f)) {
+       const bgeot::pgeometric_trans pgt = mf_source.linked_mesh().trans_of_convex(cv);
+       bgeot::vectors_to_base_matrix(G, mf_source.linked_mesh().points_of_convex(cv));
+       if (f != short_type(-1))
+         normal_on_convex_face(pgt, G, f, ptref, normal);
+       else
+         normal_on_convex(pgt, G, ptref, normal);
+       base_node ppt = pgt->transform(ptref, G);
+       gap = gmm::vect_sp(pt-ppt, normal);
+     }
+     else { // return undefined normal vector and huge gap
+       normal = base_node(pt.size());
+       gap = 1e12;
++>>>>>>> upstream
      }
  
    }
@@@ -727,7 -790,7 +903,11 @@@
        ming = std::min(ming, v[cv]);
        maxg = std::max(maxg, v[cv]);
        meang += v[cv];
++<<<<<<< HEAD
 +      if (v[cv] > 0) ++cntg; 
++=======
+       if (v[cv] > 0) ++cntg;
++>>>>>>> upstream
      }
      meang /= scalar_type(cntg);
    }
diff --cc src/gmm/gmm_MUMPS_interface.h
index 71a9b44,da6a01d..43dc6c9
--- a/src/gmm/gmm_MUMPS_interface.h
+++ b/src/gmm/gmm_MUMPS_interface.h
@@@ -280,32 -316,6 +316,35 @@@ namespace gmm 
    }
  
  
++<<<<<<< HEAD
 +  template <typename MUMPS_STRUCT>
 +  static inline bool mumps_error_check(MUMPS_STRUCT &id) {
 +#define INFO(I) info[(I)-1]
 +    if (id.INFO(1) < 0) {
 +      switch (id.INFO(1)) {
 +        case -2:
 +          GMM_ASSERT1(false, "Solve with MUMPS failed: NZ = " << id.INFO(2)
 +                      << " is out of range");
 +        case -6 : case -10 :
 +          GMM_WARNING1("Solve with MUMPS failed: matrix is singular");
 +          return false;
 +        case -9:
 +          GMM_ASSERT1(false, "Solve with MUMPS failed: error "
 +                      << id.INFO(1) << ", increase ICNTL(14)");
 +        case -13 :
 +          GMM_ASSERT1(false, "Solve with MUMPS failed: not enough memory");
 +        default :
 +          GMM_ASSERT1(false, "Solve with MUMPS failed with error "
 +                      << id.INFO(1));
 +      }
 +    }
 +    return true;
 +#undef INFO
 +  }
 +
 +
++=======
++>>>>>>> upstream
  }
  
    
diff --cc src/gmm/gmm_std.h
index cc1d7e0,dffde8d..08272af
--- a/src/gmm/gmm_std.h
+++ b/src/gmm/gmm_std.h
@@@ -1,32 -1,32 +1,62 @@@
  /* -*- c++ -*- (enables emacs c++ mode) */
  /*===========================================================================
++<<<<<<< HEAD
 + 
 + Copyright (C) 2002-2012 Yves Renard
 + 
 + This file is a part of GETFEM++
 + 
 + Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
 + Exception either version 3.1 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 Lesser General Public
 + License and GCC Runtime Library Exception for more details.
 + You  should  have received a copy of the GNU Lesser General Public License
 + along  with  this program;  if not, write to the Free Software Foundation,
 + Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
 + 
 + As a special exception, you  may use  this file  as it is a part of a free
 + software  library  without  restriction.  Specifically,  if   other  files
 + instantiate  templates  or  use macros or inline functions from this file,
 + or  you compile this  file  and  link  it  with other files  to produce an
 + executable, this file  does  not  by itself cause the resulting executable
 + to be covered  by the GNU Lesser General Public License.  This   exception
 + does not  however  invalidate  any  other  reasons why the executable file
 + might be covered by the GNU Lesser General Public License.
 + 
++=======
+ 
+ Copyright (C) 2002-2012 Yves Renard
+ 
+ This file is a part of GETFEM++
+ 
+ Getfem++  is  free software;  you  can  redistribute  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 along with the GCC Runtime Library
+ Exception either version 3.1 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 Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ 
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+ 
++>>>>>>> upstream
  ===========================================================================*/
  
  /**@file gmm_std.h
@@@ -129,17 -125,67 +155,81 @@@
  #include <limits>
  #include <sstream>
  #include <numeric>
++<<<<<<< HEAD
 +
 +
 +namespace gmm {
 +
 +  using std::endl; using std::cout; using std::cerr;
 +  using std::ends; using std::cin;
 +
 +
 +  /* ********************************************************************* */
 +  /*       Change locale temporarily.                                      */
 +  /* ********************************************************************* */
++=======
+ #include <locale.h>
+ #include <omp.h>
+ 
+ #ifdef _OPENMP	
+ 	/**number of OpenMP threads*/
+ 	inline size_t num_threads(){return omp_get_max_threads();}
+ 	/**index of the current thread*/
+ 	inline size_t this_thread() {return omp_get_thread_num();}
+ 	/**is the program running in the parallel section*/
+ 	inline bool me_is_multithreaded_now(){return static_cast<bool>(omp_in_parallel());}
+ #else
+ 	inline size_t num_threads(){return size_t(1);}
+ 	inline size_t this_thread() {return size_t(0);}
+ 	inline bool me_is_multithreaded_now(){return false;}
+ #endif
+ 
+ namespace gmm {
+ 
+ 	using std::endl; using std::cout; using std::cerr;
+ 	using std::ends; using std::cin;
+ 
+ #ifdef _WIN32
+ 
+ 	class standard_locale {
+ 		std::string cloc;
+ 		std::locale cinloc;
+ 	public :
+ 		inline standard_locale(void) : cinloc(cin.getloc())
+ 		{
+ 			if (!me_is_multithreaded_now()){ 
+ 				 cloc=setlocale(LC_NUMERIC, 0);
+ 				 setlocale(LC_NUMERIC,"C"); 
+ 			}
+ 		}
+ 
+ 		inline ~standard_locale() {
+ 			if (!me_is_multithreaded_now()) 
+ 					setlocale(LC_NUMERIC, cloc.c_str()); 
+ 			
+ 		}
+ 	};
+ #else
+ 	/**this is the above solutions for linux, but I still needs to be tested.*/
+ 	//class standard_locale {
+ 	//	locale_t oldloc;
+ 	//	locale_t temploc;
+ 
+ 	//public :
+ 	//	inline standard_locale(void) : oldloc(uselocale((locale_t)0))
+ 	//	{       
+ 	//			temploc = newlocale(LC_NUMERIC, "C", NULL);
+     //              uselocale(temploc);
+ 	//	}
+ 
+ 	//	inline ~standard_locale()
+ 	//	{
+ 	//		    uselocale(oldloc);
+ 	//			freelocale(temploc);
+ 	//	}
+ 	//};
+ 
++>>>>>>> upstream
  
    class standard_locale {
      std::string cloc;
diff --cc src/gmm/gmm_sub_index.h
index 690078b,7221e07..cfc23ed
--- a/src/gmm/gmm_sub_index.h
+++ b/src/gmm/gmm_sub_index.h
@@@ -153,7 -153,7 +153,11 @@@ namespace gmm 
      template <typename CONT> unsorted_sub_index(const CONT &c)
        : sub_index(c) {}
      unsorted_sub_index() {}
++<<<<<<< HEAD
 +    unsorted_sub_index(const unsorted_sub_index &si) : sub_index((sub_index &)(si)) { }
++=======
+     unsorted_sub_index(const unsorted_sub_index &si) : sub_index((const sub_index &)(si)) { }
++>>>>>>> upstream
      unsorted_sub_index &operator =(const unsorted_sub_index &si)
      { sub_index::operator =(si); return *this; }
      void swap(size_type i, size_type j) {
diff --cc tests/Makefile.am
index 6912559,861868b..1d2c030
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@@ -108,43 -108,43 +108,83 @@@ AM_CPPFLAGS = -I$(top_srcdir)/src -I../
  LDADD    = ../src/libgetfem.la -lm $(SUPLDFLAGS)
  
  TESTS = \
++<<<<<<< HEAD
 +	$(top_srcdir)/tests/dynamic_array.pl              \
 +	$(top_srcdir)/tests/dynamic_tas.pl                \
 +	$(top_srcdir)/tests/test_int_set.pl               \
 +	$(top_srcdir)/tests/test_tree_sorted.pl           \
 +	$(top_srcdir)/tests/poly.pl                       \
 +	$(top_srcdir)/tests/test_small_vector.pl          \
 +	$(top_srcdir)/tests/test_kdtree.pl                \
 +	$(top_srcdir)/tests/test_rtree.pl                 \
 +	$(top_srcdir)/tests/geo_trans_inv.pl              \
 +	$(top_srcdir)/tests/test_norm.pl                  \
 +	$(top_srcdir)/tests/test_mesh.pl                  \
 +	$(top_srcdir)/tests/test_interpolation.pl         \
 +	$(top_srcdir)/tests/test_mat_elem.pl              \
 +	$(top_srcdir)/tests/test_slice.pl                 \
 +	$(top_srcdir)/tests/integration.pl                \
 +	$(top_srcdir)/tests/test_assembly.pl              \
 +	$(top_srcdir)/tests/test_interpolated_fem.pl      \
 +	$(top_srcdir)/tests/test_range_basis.pl           \
 +	$(top_srcdir)/tests/laplacian.pl                  \
 +	$(top_srcdir)/tests/laplacian_with_bricks.pl      \
 +	$(top_srcdir)/tests/elastostatic.pl               \
 +	$(top_srcdir)/tests/stokes.pl                     \
 +	$(top_srcdir)/tests/plate.pl                      \
 +	$(optpl)                                          \
 +	$(top_srcdir)/tests/nonlinear_elastostatic.pl     \
 +	$(top_srcdir)/tests/nonlinear_membrane.pl         \
 +	$(top_srcdir)/tests/dynamic_friction.pl           \
 +	$(top_srcdir)/tests/plasticity.pl                 \
 +	$(top_srcdir)/tests/plasticity_old_brick.pl       \
 +	$(top_srcdir)/tests/helmholtz.pl                  \
 +	$(top_srcdir)/tests/schwarz_additive.pl           \
 +	$(top_srcdir)/tests/bilaplacian.pl    	          \
 +	$(top_srcdir)/tests/heat_equation.pl              \
 +	$(top_srcdir)/tests/wave_equation.pl   	          \
 +	$(top_srcdir)/tests/test_large_sliding_contact.pl \
 +	$(top_srcdir)/tests/cyl_slicer.pl	          \
 +	$(top_srcdir)/tests/make_gmm_test.pl
++=======
+ 	$(abs_top_srcdir)/tests/dynamic_array.pl              \
+ 	$(abs_top_srcdir)/tests/dynamic_tas.pl                \
+ 	$(abs_top_srcdir)/tests/test_int_set.pl               \
+ 	$(abs_top_srcdir)/tests/test_tree_sorted.pl           \
+ 	$(abs_top_srcdir)/tests/poly.pl                       \
+ 	$(abs_top_srcdir)/tests/test_small_vector.pl          \
+ 	$(abs_top_srcdir)/tests/test_kdtree.pl                \
+ 	$(abs_top_srcdir)/tests/test_rtree.pl                 \
+ 	$(abs_top_srcdir)/tests/geo_trans_inv.pl              \
+ 	$(abs_top_srcdir)/tests/test_norm.pl                  \
+ 	$(abs_top_srcdir)/tests/test_mesh.pl                  \
+ 	$(abs_top_srcdir)/tests/test_interpolation.pl         \
+ 	$(abs_top_srcdir)/tests/test_mat_elem.pl              \
+ 	$(abs_top_srcdir)/tests/test_slice.pl                 \
+ 	$(abs_top_srcdir)/tests/integration.pl                \
+ 	$(abs_top_srcdir)/tests/test_assembly.pl              \
+ 	$(abs_top_srcdir)/tests/test_interpolated_fem.pl      \
+ 	$(abs_top_srcdir)/tests/test_range_basis.pl           \
+ 	$(abs_top_srcdir)/tests/laplacian.pl                  \
+ 	$(abs_top_srcdir)/tests/laplacian_with_bricks.pl      \
+ 	$(abs_top_srcdir)/tests/elastostatic.pl               \
+ 	$(abs_top_srcdir)/tests/stokes.pl                     \
+ 	$(abs_top_srcdir)/tests/plate.pl                      \
+ 	$(optpl)                                          \
+ 	$(abs_top_srcdir)/tests/nonlinear_elastostatic.pl     \
+ 	$(abs_top_srcdir)/tests/nonlinear_membrane.pl         \
+ 	$(abs_top_srcdir)/tests/dynamic_friction.pl           \
+ 	$(abs_top_srcdir)/tests/plasticity.pl                 \
+ 	$(abs_top_srcdir)/tests/plasticity_old_brick.pl       \
+ 	$(abs_top_srcdir)/tests/helmholtz.pl                  \
+ 	$(abs_top_srcdir)/tests/schwarz_additive.pl           \
+ 	$(abs_top_srcdir)/tests/bilaplacian.pl    	          \
+ 	$(abs_top_srcdir)/tests/heat_equation.pl              \
+ 	$(abs_top_srcdir)/tests/wave_equation.pl   	          \
+ 	$(abs_top_srcdir)/tests/test_large_sliding_contact.pl \
+ 	$(abs_top_srcdir)/tests/cyl_slicer.pl	          \
+ 	$(abs_top_srcdir)/tests/make_gmm_test.pl
++>>>>>>> upstream
  
  EXTRA_DIST =                               			\
  	dynamic_array.pl                   			\
@@@ -230,6 -230,8 +270,11 @@@
  	meshes/donut_regulier_32_elements.mesh			\
  	meshes/sphere_with_quadratic_tetra_8_elts.mesh		\
  	meshes/disc_with_a_hole.mesh				\
++<<<<<<< HEAD
++=======
+ 	meshes/punch2D_h2.mesh					\
+ 	meshes/multi_body.mesh					\
++>>>>>>> upstream
  	meshes/donut_regulier_512_elements.mesh
  
  
diff --cc tests/test_continuation.cc
index ccd479d,1c3dd21..d8e1a90
--- a/tests/test_continuation.cc
+++ b/tests/test_continuation.cc
@@@ -33,6 -33,7 +33,10 @@@
  #include "getfem/getfem_regular_meshes.h"
  #include "getfem/getfem_model_solvers.h"
  #include "getfem/getfem_continuation.h" /* import continuation method */
++<<<<<<< HEAD
++=======
+ #include "gmm/gmm_inoutput.h"
++>>>>>>> upstream
  
  using std::endl; using std::cout; using std::cerr;
  using std::ends; using std::cin;
@@@ -55,7 -56,6 +59,10 @@@ struct state_problem 
    getfem::mesh_im mim;       /* the integration method */
    scalar_type lambda;
  
++<<<<<<< HEAD
 +  std::string datafilename;
++=======
++>>>>>>> upstream
    bgeot::md_param PARAM;
  
    bool cont(plain_vector &U);
@@@ -76,11 -76,8 +83,16 @@@ void state_problem::init(void) 
    
    /* First step: build the mesh */
    std::vector<getfem::size_type> nsubdiv(1);
++<<<<<<< HEAD
 +  nsubdiv[0] = PARAM.int_value("NX", "Number of the space steps ");
 +  regular_unit_mesh(mesh, nsubdiv, bgeot::simplex_geotrans(1, 1));
 +  
 +  datafilename = PARAM.string_value("ROOTFILENAME",
 +				    "Base name of data files.");
++=======
+   nsubdiv[0] = PARAM.int_value("NX", "Number of space steps ");
+   regular_unit_mesh(mesh, nsubdiv, bgeot::simplex_geotrans(1, 1));
++>>>>>>> upstream
  
    /* set the finite element on the mf_u */
    getfem::pfem pf_u = getfem::fem_descriptor(FEM_TYPE);
@@@ -103,8 -100,7 +115,12 @@@ bool state_problem::cont(plain_vector &
    model.add_fem_variable("u", mf_u);
    add_Laplacian_brick(model, mim, "u");
    std::string f = "u-lambda*exp(u)", dfdu = "1-lambda*exp(u)";
++<<<<<<< HEAD
 +  lambda = PARAM.real_value("LAMBDA0");
 +  model.add_initialized_scalar_data("lambda", lambda);
++=======
+   model.add_fixed_size_data("lambda", 1);
++>>>>>>> upstream
    add_basic_nonlinear_brick(model, mim, "u", f, dfdu,
  			    size_type(-1), "lambda");
  
@@@ -113,53 -109,112 +129,159 @@@
    getfem::rmodel_plsolver_type ls =
      getfem::default_linear_solver<getfem::model_real_sparse_matrix,
                                    getfem::model_real_plain_vector>(model);
++<<<<<<< HEAD
 +  size_type nb_step = int(PARAM.int_value("NBSTEP")),
 +    maxit = PARAM.int_value("MAXITER"),
 +    thrit = PARAM.int_value("THR_ITER"),
 +    nb_dof = mf_u.nb_dof();
 +  scalar_type scfac = 1./ nb_dof,
 +    maxres = PARAM.real_value("RESIDUAL"),
 +    maxdiff = PARAM.real_value("DIFFERENCE"),
 +    minang = PARAM.real_value("ANGLE"),
 +    h_init = PARAM.real_value("H_INIT"),
 +    h_max = PARAM.real_value("H_MAX"),
 +    h_min = PARAM.real_value("H_MIN"),
 +    h_inc = PARAM.real_value("H_INC"),
 +    h_dec = PARAM.real_value("H_DEC"),
 +    eps = PARAM.real_value("EPSILON"),
 +    maxres_solve = PARAM.real_value("RESIDUAL_SOLVE");
 +  int noisy = PARAM.int_value("NOISY");
 +  getfem::cont_struct_getfem_model
 +    S(model, "lambda", ls, scfac, maxit, thrit, maxres, maxdiff, minang,
 +      h_init, h_max, h_min, h_inc, h_dec, eps, maxres_solve, noisy);
 +
 +  if (noisy > 0) cout << "computing initial point" << endl;
 +  gmm::iteration iter(maxres_solve, noisy, 40000);
 +  getfem::standard_solve(model, iter);
 +
 +  gmm::resize(U, nb_dof);
 +  gmm::copy(model.real_variable("u"), U);
++=======
+   size_type nb_dof = mf_u.nb_dof();
+   scalar_type scfac = 1./ nb_dof;
+   size_type nb_step = int(PARAM.int_value("NBSTEP",
+ 					  "Number of continuation steps"));
+   bool bifurcations = PARAM.int_value("BIFURCATIONS", 
+ 				      "Deal with bifurcations?");
+   scalar_type  h_init = PARAM.real_value("H_INIT", "h_init"),
+     h_max = PARAM.real_value("H_MAX", "h_max"),
+     h_min = PARAM.real_value("H_MIN", "h_min"),
+     h_inc = PARAM.real_value("H_INC", "h_inc"),
+     h_dec = PARAM.real_value("H_DEC", "h_dec");
+   size_type  maxit = PARAM.int_value("MAXITER", "maxit"),
+     thrit = PARAM.int_value("THR_ITER", "thrit");
+   scalar_type maxres = PARAM.real_value("RESIDUAL", "maxres"),
+     maxdiff = PARAM.real_value("DIFFERENCE", "maxdiff"),
+     mincos = PARAM.real_value("COS", "mincos"),
+     maxres_solve = PARAM.real_value("RESIDUAL_SOLVE", "maxres_solve");
+   int noisy = PARAM.int_value("NOISY", "noisy");
+   std::string datapath = PARAM.string_value("DATAPATH",
+ 					    "Directory of data files");
+   gmm::set_traces_level(noisy - 1);
+   getfem::cont_struct_getfem_model
+     S(model, "lambda", scfac, ls, bifurcations, h_init, h_max, h_min, h_inc,
+       h_dec, maxit, thrit, maxres, maxdiff, mincos, maxres_solve, noisy);
+ 
+   std::string bp_rootfilename = PARAM.string_value("BP_ROOTFILENAME").size()
+     ? PARAM.string_value("BP_ROOTFILENAME") : "";
+   scalar_type direction = PARAM.real_value("DIRECTION", "Initial direction"),
+     h, T_lambda;
+   plain_vector T_U(U), Y(nb_dof + 1);
+   
+   if (bp_rootfilename.size() > 0) {
+     gmm::vecload(datapath + bp_rootfilename + ".Y", Y);
+     gmm::copy(gmm::sub_vector(Y, gmm::sub_interval(0, nb_dof)), U);
+     lambda = Y[nb_dof];
+     char s[100];
+     sprintf(s, ".T_Y%d", (int) PARAM.int_value("IND_TANGENT",
+ 					       "Number of branches"));
+     gmm::vecload(datapath + bp_rootfilename + s, Y);
+     gmm::copy(gmm::scaled(gmm::sub_vector(Y, gmm::sub_interval(0, nb_dof)),
+ 			  direction), T_U);
+     T_lambda = direction * Y[nb_dof];
+     h = S.h_init();
+   } else {
+     lambda = PARAM.real_value("LAMBDA0", "lambda0");
+     model.set_real_variable("lambda")[0] = lambda;   
+     if (noisy > 0) cout << "computing initial point" << endl;
+     gmm::iteration iter(maxres_solve, noisy - 1, 40000);
+     getfem::standard_solve(model, iter);
+     gmm::copy(model.real_variable("u"), U);
+     T_lambda = direction;
+ 
+     getfem::init_Moore_Penrose_continuation(S, U, lambda, T_U, T_lambda, h);
+   }
++>>>>>>> upstream
  
    cout << "U = " << U << endl;
    cout << "lambda - u * exp(-u) = " << lambda - U[0] * exp(-U[0]) << endl;
  
++<<<<<<< HEAD
 +  plain_vector T_U(U);
 +  scalar_type T_lambda = PARAM.real_value("DIRECTION"), h;
 +  getfem::init_Moore_Penrose_continuation(S, U, lambda, T_U, T_lambda, h);
 +
 +  // Continuation
 +  for (size_type step = 0; step < nb_step; ++step) {
 +    cout << endl << "beginning of step " << step + 1 << endl;
 +    
++=======
+   // Continuation
+   std::string sing_label;
+   char s1[100], s2[100];
+   std::vector<std::string> sing_out;
+   for (size_type step = 0; step < nb_step; ++step) {
+     cout << endl << "beginning of step " << step + 1 << endl;
+    
++>>>>>>> upstream
      getfem::Moore_Penrose_continuation(S, U, lambda, T_U, T_lambda, h);
      if (h == 0) break;
  
      cout << "U = " << U << endl;
      cout << "lambda = " << lambda << endl;
++<<<<<<< HEAD
 +    cout << "lambda - U[0] * exp(-U[0]) = "
 +	 << lambda - U[0] * exp(-U[0]) << endl;
 +
 +    cout << "end of Step nº " << step+1 << " / " << nb_step << endl;
++=======
+ //     cout << "lambda - U[0] * exp(-U[0]) = "
+ // 	 << lambda - U[0] * exp(-U[0]) << endl;
+ 
+     sing_label = S.get_sing_label();
+     if (sing_label == "smooth bifurcation point") {
+       gmm::copy(S.get_x_sing(),
+ 		gmm::sub_vector(Y, gmm::sub_interval(0, nb_dof)));
+       Y[nb_dof] = S.get_gamma_sing();
+       sprintf(s1, "continuation_step_%d", step + 1);
+       gmm::vecsave(datapath + s1 + "_bp.Y", Y);
+ 
+       for (size_type i = 0; i < S.nb_tangent_sing(); i++) {
+ 	gmm::copy(S.get_t_x_sing(i),
+ 		  gmm::sub_vector(Y, gmm::sub_interval(0, nb_dof)));
+ 	Y[nb_dof] = S.get_t_gamma_sing(i);
+ 	sprintf(s2, "_bp.T_Y%d", i + 1);
+ 	gmm::vecsave(datapath + s1 + s2, Y);
+       }
+ 
+       sprintf(s1, "Step %d: %u branch(es) located",
+ 	      step + 1, (unsigned int) S.nb_tangent_sing());
+       sing_out.push_back(s1);
+     }
+     cout << "end of Step nº " << step + 1 << " / " << nb_step << endl;
+   }
+ 
+   if (sing_out.size() > 0) {
+     cout << endl
+ 	 << "----------------------------------------------------------" 
+ 	 << endl
+ 	 << "   Detected bifurcation points on the continuation curve"
+ 	 << endl
+ 	 << "----------------------------------------------------------"
+ 	 << endl;
+     for (size_type i = 0; i < sing_out.size(); i++)
+       cout << sing_out[i] << endl << endl;
++>>>>>>> upstream
    }
  
    return (h > 0);
@@@ -179,7 -234,7 +301,11 @@@ int main(int argc, char *argv[]) 
      p.PARAM.read_command_line(argc, argv);
      p.init();
      plain_vector U(p.mf_u.nb_dof());
++<<<<<<< HEAD
 +    if (!p.cont(U)) GMM_ASSERT1(false, "Continuation has failed");
++=======
+     p.cont(U); 
++>>>>>>> upstream
    }
    GMM_STANDARD_CATCH_ERROR;
  
diff --cc tests/test_continuation.param
index a325d67,6a42573..321a7f2
--- a/tests/test_continuation.param
+++ b/tests/test_continuation.param
@@@ -3,34 -3,36 +3,68 @@@
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  %%%%%   discretisation parameters:	                     	      %%%%%
++<<<<<<< HEAD
 +NX = 10;            	          % space step.
 +FEM_TYPE = 'FEM_PK(1,1)';  % P1 for segments
 +INTEGRATION = 'IM_GAUSS1D(3)'; % Gauss-Legendre integration on the
 +                               % segment of order 3
 +
 +%%%%%   continuation parameters:	                     	      %%%%%
 +LAMBDA0 = 0.;		% initial value of the parameter lambda
 +DIRECTION = 1.;		% direction of the continuation
 +NBSTEP = 100;		% number of the continuation steps
++=======
+ NX = 10;            	       % space step
+ FEM_TYPE = 'FEM_PK(1,1)';      % P1 for segments
+ INTEGRATION = 'IM_GAUSS1D(3)'; % Gauss-Legendre integration on the
+                                % segment of order 3
+ 
+ %%%%%   continuation data:		                     	      %%%%%
+ DATAPATH = 'data/';
+ %BP_ROOTFILENAME = 'continuation_step_62_bp';	% root of the file with 
+ 					% bifurcation data to be loaded
+ IND_TANGENT = 2;	% index of the tangent to be loaded when starting 
+ 			% from a bifurcation point
+ DIRECTION = 1.;		% direction of the initial tangent
+ LAMBDA0 = 0.;		% initial value of parameter
+ NBSTEP = 80;		% number of continuation steps
+ 
+ BIFURCATIONS = 1;	% deal with bifurcations?
+ H_INIT = 2E-2;		% initial step length
+ H_MAX = 2E-1;		% maximal step length
+ H_MIN = 2E-5;		% minimal step length
+ H_INC = 1.3;		% scale factor for increasing the step length
+ H_DEC = 0.5;		% scale factor for decreasing the step length
++>>>>>>> upstream
  
  MAXITER = 5;		% maximum iterations of the Newton correction
  THR_ITER = 4;		% threshold for the number of iterations for
  			% increasing the step length
  RESIDUAL = 1E-6;     	% residual
++<<<<<<< HEAD
 +DIFFERENCE = 1E-9;	% difference of two forthcoming iteratives
 +ANGLE = 0.993; 		% cosine of the angle between tangents at
 +			% two forthcoming points
 +
 +H_INIT = 1E-3;		% initial step length
 +H_MAX = 2E-1;		% maximal step length
 +H_MIN = 1E-5;		% minimal step length
 +H_INC = 1.3;		% scale factor for increasing the step length
 +H_DEC = 0.5;		% scale factor for decreasing the step length
 +
 +EPSILON = 1E-8;		% spacing for finite differences
 +RESIDUAL_SOLVE = 1E-7;	% initial residual
 +
 +
 +%%%%%   saving and output parameters                                  %%%%%
 +ROOTFILENAME = 'continuation';     % Root of data files.
 +NOISY = 2;
++=======
+ DIFFERENCE = 1E-6;	% difference of two forthcoming iteratives
+ COS = 0.997; 		% cosine of the angle between tangents at
+ 			% two forthcoming points
+ RESIDUAL_SOLVE = 1E-8;	% initial residual
+ 
+ %%%%%   output parameters     		                             %%%%%
+ NOISY = 0;
++>>>>>>> upstream
diff --cc tests/test_large_sliding_contact.cc
index ff4e628,bcfa33b..7c49b08
--- a/tests/test_large_sliding_contact.cc
+++ b/tests/test_large_sliding_contact.cc
@@@ -33,6 -33,7 +33,10 @@@
  #include "getfem/getfem_regular_meshes.h"
  #include "getfem/getfem_contact_and_friction_integral.h"
  #include "getfem/getfem_contact_and_friction_common.h"
++<<<<<<< HEAD
++=======
+ #include "getfem/getfem_contact_and_friction_large_sliding.h"
++>>>>>>> upstream
  #include "getfem/getfem_model_solvers.h"
  #include "gmm/gmm.h"
  #include <fstream>
@@@ -398,7 -399,7 +402,11 @@@ void contact_problem::solve(void) 
    // Contact brick.
    model.add_initialized_scalar_data("r", R);
    model.add_initialized_scalar_data("f", friction_coef);
++<<<<<<< HEAD
 +  size_type indb = add_integral_large_sliding_contact_brick
++=======
+   size_type indb = add_integral_large_sliding_contact_brick_field_extension
++>>>>>>> upstream
      (model, mim2, "u2", "lambda2", "r", "f", CONTACT_BOUNDARY2);
  
    if (two_bodies) 

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



More information about the debian-science-commits mailing list