Coverage for pyxfem/postpro/interpolator.py: 17%
84 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-24 07:17 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-24 07:17 +0000
1''' define interpolator from mesh field '''
2from warnings import warn
3import numpy as np
4from matplotlib.tri import Triangulation
5from pyxfem.core.config import npfloat
6from pyxfem.core.mapping import MappingT3
8def get_triangulation(xy, t2v):
9 ''' return a matplotlib.tri.Triangulation from
10 - a set of point xy and triangle connectivity t2xy '''
11 return Triangulation(xy[:,0], xy[:,1], t2v)
13def get_trifinder( xy, t2v):
14 ''' return a matplotlib "trifinder " : a function that return the triangle number in
15 which each point it is called on is in '''
16 tri = get_triangulation(xy, t2v)
17 trif = tri.get_trifinder()
18 def finder(xyp):
19 return trif(xyp[...,0], xyp[...,1])
20 return finder
22class ConstantPerTriInterpolator():
23 ''' Constant per Element field interpolator : find in which element is a point and return
24 the corresponding element consant value'''
25 def __init__(self, xy, t2v, values, trifinder = None):
26 ''' values are the per element values, mus also pass either a trifinder objet or a sMesh'''
27 if trifinder is None:
28 self.trifinder = get_trifinder(xy, t2v)
29 else :
30 self.trifinder = trifinder
31 self.values = values
32 def __call__(self, xy):
33 elems = self.trifinder(xy)
34 return self.values[elems]
36class LinearPerTriInterpolator():
37 ''' linear per Element field interpolator field is supposed C0 on the input mesh,
38 and linear per element input : value at node and mesh.
39 '''
40 def __init__(self, xy, t2v, values, trifinder = None):
41 ''' values are the per node values, must also pass either a trifinder objet or a sMesh'''
42 if trifinder is None:
43 self.trifinder = get_trifinder(xy, t2v)
44 else :
45 self.trifinder = trifinder
46 self.t2v = t2v
47 t3xy = xy[t2v]
48 self.map = MappingT3(t3xy)
49 self.values = values
50 assert(values.shape[0] == xy.shape[0])
51 self.fieldshape = values.shape[1:]
53 def __call__(self, xy):
54 xy = np.atleast_2d(xy)
55 elems = np.asarray(self.trifinder(xy), dtype =int)
56 xy0 = self.map.xy[elems, 0, :]
57 xy0s = xy - xy0
58 uv = np.einsum('...jl,...l->...j', self.map.inv_F[elems], xy0s)
59 valelems = self.values[self.t2v[elems]]
60 u = uv[...,0]
61 v = uv[...,1]
62 shape = u.shape + tuple(1 for i in range(len(self.fieldshape)))
63 u = u.reshape(shape)
64 v = v.reshape(shape)
65 nodeaxis = -1-len(self.fieldshape)
66 valelemsv0 = valelems.take(0, axis = nodeaxis )
67 valelemsv1 = valelems.take(1, axis = nodeaxis )
68 valelemsv2 = valelems.take(2, axis = nodeaxis )
69 val = valelemsv0 + (valelemsv1-valelemsv0)*u + (valelemsv2-valelemsv0)*v
70 if np.any(elems < 0) :
71 warn("some point are outside of the mesh linearPerTriInterpolator," \
72 " corresponding values are set to np.inf")
73 val[elems < 0] = np.inf
74 return np.asarray(val, dtype = npfloat)
76if __name__ == '__main__':
77 import gmsh
78 import pyxfem.core.gmsh_mesh_generator as mg
79 from pyxfem.core.mesh_simplex_one_level import gmshmodel2smesh
80 import pyxfem.postpro.gmsh_post_pro_interface as gp
81 gmsh.initialize()
82 gmsh.option.setNumber("PostProcessing.AnimationCycle", 1)
83 gmsh.option.setNumber('General.Terminal', 0)
84 #model_name1, ____ = mg.square(length=1., relh=0.1, transfinite = True)
85 model_name1, ____ = mg.crack_in_square_contour(relh = 0.1)
86 gmsh.fltk.run()
87 mesh1 = gmshmodel2smesh(model_name1)
88 model_name2, ____ = mg.l_shape(relh=0.05)
89 mesh2 = gmshmodel2smesh(model_name2)
90 def fun_scal(xy):
91 ''' a simple scalar function of coordinate '''
92 return xy[...,0]**2
93 def fun_vec(xy):
94 ''' a simple vector function of coordinate '''
95 return xy
96 fun = fun_scal
97 mesh1_trixy = mesh1.t2v_coord()
98 gp.listPlotFieldTri(mesh1_trixy, fun(mesh1_trixy),
99 viewname='base scalar field on mesh1', Range =[0.,0.25])
100 interp = LinearPerTriInterpolator(mesh1.xy, mesh1.t2v, fun(mesh1.xy))
101 val2 = interp(mesh2.xy)
102 gp.listPlotFieldTri(mesh2.t2v_coord(), val2[np.asarray(mesh2.t2v, dtype=int)],
103 viewname='interp scalar field on mesh2', Range =[0.,0.25])
105 fun = fun_vec
106 mesh1_trixy = mesh1.t2v_coord()
107 gp.listPlotFieldTri(mesh1_trixy, fun(mesh1_trixy),
108 viewname='base vector field on mesh1', Range = [0., np.sqrt(2)])
109 interp = LinearPerTriInterpolator(mesh1.xy, mesh1.t2v, fun(mesh1.xy), trifinder=interp.trifinder)
110 val2 = interp(mesh2.xy)
111 gp.listPlotFieldTri(mesh2.t2v_coord(), val2[np.asarray(mesh2.t2v, dtype=int)],
112 viewname='interp vector field on mesh2', Range = [0., np.sqrt(2)])
113 gmsh.fltk.run()