Version: 8.3.0
 All Classes Namespaces Files Functions Variables Groups Pages
Creating Meshes


First of all see Example of 3d mesh generation, which is an example of good python script style for Mesh module.


Construction of a mesh

1 # Construction of a Mesh
2 
3 import salome
4 salome.salome_init()
5 import GEOM
6 from salome.geom import geomBuilder
7 geompy = geomBuilder.New(salome.myStudy)
8 
9 import SMESH, SALOMEDS
10 from salome.smesh import smeshBuilder
11 smesh = smeshBuilder.New(salome.myStudy)
12 
13 # create a box
14 box = geompy.MakeBox(0., 0., 0., 100., 200., 300.)
15 idbox = geompy.addToStudy(box, "box")
16 
17 # create a mesh
18 tetra = smesh.Mesh(box, "MeshBox")
19 
20 algo1D = tetra.Segment()
21 algo1D.NumberOfSegments(7)
22 
23 algo2D = tetra.Triangle()
24 algo2D.MaxElementArea(800.)
25 
26 algo3D = tetra.Tetrahedron()
27 algo3D.MaxElementVolume(900.)
28 
29 # compute the mesh
30 ret = tetra.Compute()
31 if ret == 0:
32  print "problem when computing the mesh"
33 else:
34  print "mesh computed"
35  pass

Download this script


Construction of a sub-mesh

1 # Construction of a Sub-mesh
2 
3 import salome
4 salome.salome_init()
5 import GEOM
6 from salome.geom import geomBuilder
7 geompy = geomBuilder.New(salome.myStudy)
8 
9 import SMESH, SALOMEDS
10 from salome.smesh import smeshBuilder
11 smesh = smeshBuilder.New(salome.myStudy)
12 
13 # create a box
14 box = geompy.MakeBoxDXDYDZ(10., 10., 10.)
15 geompy.addToStudy(box, "Box")
16 
17 # select one edge of the box for definition of a local hypothesis
18 p5 = geompy.MakeVertex(5., 0., 0.)
19 EdgeX = geompy.GetEdgeNearPoint(box, p5)
20 geompy.addToStudyInFather(box, EdgeX, "Edge [0,0,0 - 10,0,0]")
21 
22 # create a hexahedral mesh on the box
23 mesh = smesh.Mesh(box, "Box : hexahedral 3D mesh")
24 
25 # create a Regular_1D algorithm for discretization of edges
26 algo1D = mesh.Segment()
27 
28 # define "NumberOfSegments" hypothesis to cut
29 # all the edges in a fixed number of segments
30 algo1D.NumberOfSegments(4)
31 
32 # create a quadrangle 2D algorithm for the faces
33 mesh.Quadrangle()
34 
35 # construct a sub-mesh on the edge with a local Regular_1D algorithm
36 algo_local = mesh.Segment(EdgeX)
37 
38 # define "Arithmetic1D" hypothesis to cut EdgeX in several segments with length arithmetically
39 # increasing from 1.0 to 4.0
40 algo_local.Arithmetic1D(1, 4)
41 
42 # define "Propagation" hypothesis that propagates algo_local and "Arithmetic1D" hypothesis
43 # from EdgeX to all parallel edges
44 algo_local.Propagation()
45 
46 # assign a hexahedral algorithm
47 mesh.Hexahedron()
48 
49 
50 # any sub-shape can be meshed individually --
51 # compute mesh on two surfaces using different methods
52 
53 # get surfaces
54 surfaces = geompy.SubShapeAll(box, geompy.ShapeType["FACE"])
55 
56 # method 1: no sub-mesh is created
57 mesh.Compute( surfaces[0] )
58 
59 # method 2: a sub-mesh is created
60 submesh = mesh.GetSubMesh( surfaces[2], "submesh 2" )
61 submesh.Compute()
62 
63 
64 
65 # compute the whole mesh
66 mesh.Compute()

Download this script


Change priority of sub-meshes in mesh

1 # Change priority of sub-meshes in Mesh
2 
3 import salome
4 salome.salome_init()
5 import GEOM
6 from salome.geom import geomBuilder
7 geompy = geomBuilder.New(salome.myStudy)
8 
9 import SMESH, SALOMEDS
10 from salome.smesh import smeshBuilder
11 smesh = smeshBuilder.New(salome.myStudy)
12 
13 Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
14 [Face_1,Face_2,Face_3,Face_4,Face_5,Face_6] = geompy.SubShapeAllSorted(Box_1, geompy.ShapeType["FACE"])
15 
16 # create Mesh object on Box shape
17 Mesh_1 = smesh.Mesh(Box_1)
18 
19 # assign mesh algorithms and hypotheses
20 Regular_1D = Mesh_1.Segment()
21 Nb_Segments_1 = Regular_1D.NumberOfSegments(20)
22 MEFISTO_2D = Mesh_1.Triangle()
23 Max_Element_Area_1 = MEFISTO_2D.MaxElementArea(1200)
24 Tetrahedron = Mesh_1.Tetrahedron()
25 Max_Element_Volume_1 = Tetrahedron.MaxElementVolume(40000)
26 
27 # create sub-mesh and assign algorithms on Face_1
28 Regular_1D_1 = Mesh_1.Segment(geom=Face_1)
29 Nb_Segments_2 = Regular_1D_1.NumberOfSegments(4)
30 MEFISTO_2D_1 = Mesh_1.Triangle(algo=smeshBuilder.MEFISTO,geom=Face_1)
31 SubMesh_1 = MEFISTO_2D_1.GetSubMesh()
32 
33 # create sub-mesh and assign algorithms on Face_2
34 Regular_1D_2 = Mesh_1.Segment(geom=Face_2)
35 Nb_Segments_3 = Regular_1D_2.NumberOfSegments(8)
36 MEFISTO_2D_2 = Mesh_1.Triangle(algo=smeshBuilder.MEFISTO,geom=Face_2)
37 SubMesh_2 = MEFISTO_2D_2.GetSubMesh()
38 
39 # create sub-mesh and assign algorithms on Face_3
40 Regular_1D_3 = Mesh_1.Segment(geom=Face_3)
41 Nb_Segments_4 = Regular_1D_3.NumberOfSegments(12)
42 MEFISTO_2D_3 = Mesh_1.Triangle(algo=smeshBuilder.MEFISTO,geom=Face_3)
43 SubMesh_3 = MEFISTO_2D_3.GetSubMesh()
44 
45 # check exisiting sub-mesh priority order
46 [ [ SubMesh_1, SubMesh_3, SubMesh_2 ] ] = Mesh_1.GetMeshOrder()
47 isDone = Mesh_1.Compute()
48 print "Nb elements at initial order of sub-meshes:", Mesh_1.NbElements()
49 
50 # set new sub-mesh order
51 isDone = Mesh_1.SetMeshOrder( [ [ SubMesh_1, SubMesh_2, SubMesh_3 ] ])
52 # compute mesh
53 isDone = Mesh_1.Compute()
54 print "Nb elements at new order of sub-meshes:", Mesh_1.NbElements()
55 
56 # compute with other sub-mesh order
57 isDone = Mesh_1.SetMeshOrder( [ [ SubMesh_2, SubMesh_1, SubMesh_3 ] ])
58 isDone = Mesh_1.Compute()
59 print "Nb elements at another order of sub-meshes:", Mesh_1.NbElements()

Download this script


Intermediate edition while meshing

1 import salome
2 salome.salome_init()
3 
4 from salome.geom import geomBuilder
5 geompy = geomBuilder.New(salome.myStudy)
6 
7 # This script demonstrates generation of 3D mesh basing on a modified 2D mesh
8 #
9 # Purpose is to get a tetrahedral mesh in a sphere cut by a cube.
10 # The requirement is to have a surface mesh on the cube comprised of
11 # triangles of exactly the same size arranged in a grid pattern.
12 #
13 # To fulfill this requirement we mesh the box using Quadrangle: Mapping
14 # meshing algorithm, split quadrangles into triangles and then generate
15 # tetrahedrons.
16 
17 
18 # Make the geometry
19 
20 Box_1 = geompy.MakeBox(-100,-100,-100, 100, 100, 100)
21 Sphere_1 = geompy.MakeSphereR( 300 )
22 Cut_1 = geompy.MakeCut(Sphere_1, Box_1, theName="Cut_1")
23 # get a spherical face
24 Sph_Face = geompy.ExtractShapes( Sphere_1, geompy.ShapeType["FACE"] )[0]
25 
26 # get the shape Sph_Face turned into during MakeCut()
27 Sph_Face = geompy.GetInPlace(Cut_1, Sph_Face, isNewImplementation=True, theName="Sphere_1")
28 
29 
30 # 1) Define a mesh with 1D and 2D meshers
31 
32 import SMESH
33 from salome.smesh import smeshBuilder
34 smesh = smeshBuilder.New(salome.myStudy)
35 
36 Mesh_1 = smesh.Mesh(Cut_1)
37 
38 # "global" meshers (assigned to Cut_1) that will be used for the box
39 Regular_1D = Mesh_1.Segment()
40 Local_Length_1 = Regular_1D.LocalLength(20)
41 Quadrangle_2D = Mesh_1.Quadrangle()
42 
43 # a "local" mesher (assigned to a sub-mesh on Sphere_1) to mesh the sphere
44 algo_2D = Mesh_1.Triangle( smeshBuilder.NETGEN_1D2D, Sph_Face )
45 algo_2D.SetMaxSize( 70. )
46 algo_2D.SetFineness( smeshBuilder.Moderate )
47 algo_2D.SetMinSize( 7. )
48 
49 # 2) Compute 2D mesh
50 isDone = Mesh_1.Compute()
51 
52 # 3) Split quadrangles into triangles
53 isDone = Mesh_1.SplitQuadObject( Mesh_1, Diag13=True )
54 
55 # 4) Define a 3D mesher
56 Mesh_1.Tetrahedron()
57 
58 # 5) Compute 3D mesh
59 Mesh_1.Compute()
60 
61 if salome.sg.hasDesktop():
62  salome.sg.updateObjBrowser(True)

Download this script


Editing a mesh (i.e. changing hypotheses)

1 # Editing of a mesh
2 
3 import salome
4 salome.salome_init()
5 import GEOM
6 from salome.geom import geomBuilder
7 geompy = geomBuilder.New(salome.myStudy)
8 
9 import SMESH, SALOMEDS
10 from salome.smesh import smeshBuilder
11 smesh = smeshBuilder.New(salome.myStudy)
12 
13 def PrintMeshInfo(theMesh):
14  aMesh = theMesh.GetMesh()
15  print "Information about mesh:"
16  print "Number of nodes : ", aMesh.NbNodes()
17  print "Number of edges : ", aMesh.NbEdges()
18  print "Number of faces : ", aMesh.NbFaces()
19  print "Number of volumes : ", aMesh.NbVolumes()
20  pass
21 
22 # create a box
23 box = geompy.MakeBox(0., 0., 0., 20., 20., 20.)
24 geompy.addToStudy(box, "box")
25 
26 # select one edge of the box for definition of a local hypothesis
27 subShapeList = geompy.SubShapeAll(box, geompy.ShapeType["EDGE"])
28 edge = subShapeList[0]
29 name = geompy.SubShapeName(edge, box)
30 geompy.addToStudyInFather(box, edge, name)
31 
32 # create a mesh
33 tria = smesh.Mesh(box, "Mesh 2D")
34 algo1D = tria.Segment()
35 hyp1 = algo1D.NumberOfSegments(3)
36 algo2D = tria.Triangle()
37 hyp2 = algo2D.MaxElementArea(10.)
38 
39 # create a sub-mesh
40 algo_local = tria.Segment(edge)
41 hyp3 = algo_local.Arithmetic1D(1, 6)
42 hyp4 = algo_local.Propagation()
43 
44 # compute the mesh
45 tria.Compute()
46 PrintMeshInfo(tria)
47 
48 # remove a local hypothesis
49 tria.RemoveHypothesis(hyp4, edge)
50 
51 # compute the mesh
52 tria.Compute()
53 PrintMeshInfo(tria)
54 
55 # change the value of the 2D hypothesis
56 hyp2.SetMaxElementArea(2.)
57 
58 # compute the mesh
59 tria.Compute()
60 PrintMeshInfo(tria)

Download this script


Export of a Mesh

1 # Export of a Mesh
2 
3 import salome
4 salome.salome_init()
5 import GEOM
6 from salome.geom import geomBuilder
7 geompy = geomBuilder.New(salome.myStudy)
8 
9 import SMESH, SALOMEDS
10 from salome.smesh import smeshBuilder
11 smesh = smeshBuilder.New(salome.myStudy)
12 
13 # create a box
14 box = geompy.MakeBox(0., 0., 0., 100., 200., 300.)
15 idbox = geompy.addToStudy(box, "box")
16 
17 # create a mesh
18 tetra = smesh.Mesh(box, "MeshBox")
19 tetra.Segment().NumberOfSegments(7)
20 tetra.Triangle()
21 tetra.Tetrahedron()
22 
23 # compute the mesh
24 tetra.Compute()
25 
26 # export the mesh in a MED file
27 import tempfile
28 medFile = tempfile.NamedTemporaryFile(suffix=".med").name
29 tetra.ExportMED( medFile, 0 )
30 
31 # export a group in a MED file
32 face = geompy.SubShapeAll( box, geompy.ShapeType["FACE"])[0] # a box side
33 group = tetra.GroupOnGeom( face, "face group" ) # group of 2D elements on the <face>
34 tetra.ExportMED( medFile, meshPart=group )
35 
36 # ========================
37 # autoDimension parameter
38 # ========================
39 
40 face = geompy.MakeFaceHW( 10, 10, 1, "rectangle" )
41 mesh2D = smesh.Mesh( face, "mesh2D" )
42 mesh2D.AutomaticHexahedralization(0)
43 
44 import MEDLoader, os
45 
46 # exported mesh is in 2D space because it is a planar mesh lying
47 # on XOY plane, and autoDimension=True by default
48 mesh2D.ExportMED( medFile )
49 medMesh = MEDLoader.MEDLoader.ReadUMeshFromFile(medFile,mesh2D.GetName(),0)
50 print "autoDimension==True, exported mesh is in %sD"%medMesh.getSpaceDimension()
51 
52 # exported mesh is in 3D space, same as in Mesh module,
53 # thanks to autoDimension=False
54 mesh2D.ExportMED( medFile, autoDimension=False )
55 medMesh = MEDLoader.MEDLoader.ReadUMeshFromFile(medFile,mesh2D.GetName(),0)
56 print "autoDimension==False, exported mesh is in %sD"%medMesh.getSpaceDimension()
57 
58 os.remove( medFile )

Download this script


How to mesh a cylinder with hexahedrons?

Here you can see an example of python script, creating a hexahedral mesh on a cylinder. A picture below the source code of the script demonstrates the resulting mesh.

1 # Creating a hexahedral mesh on a cylinder.
2 #
3 # This example uses Partition to divide the cylinder into blocks, which is
4 # a general approach. But for the case of cylinder there is a dedicated
5 # command creating a blocked cylinder: geompy.MakeDividedCylinder()
6 
7 import salome
8 salome.salome_init()
9 import GEOM
10 from salome.geom import geomBuilder
11 geompy = geomBuilder.New(salome.myStudy)
12 
13 import SMESH, SALOMEDS
14 from salome.smesh import smeshBuilder
15 smesh = smeshBuilder.New(salome.myStudy)
16 
17 import math
18 
19 # Parameters
20 # ----------
21 
22 radius = 50
23 height = 200
24 
25 # Build a cylinder
26 # ----------------
27 
28 base = geompy.MakeVertex(0, 0, 0)
29 direction = geompy.MakeVectorDXDYDZ(0, 0, 1)
30 
31 cylinder = geompy.MakeCylinder(base, direction, radius, height)
32 
33 geompy.addToStudy(cylinder, "cylinder")
34 
35 # Build blocks
36 # ------------
37 
38 size = radius/2.0
39 
40 box_rot = geompy.MakeBox(-size, -size, 0, +size, +size, height)
41 box_axis = geompy.MakeLine(base, direction)
42 box = geompy.MakeRotation(box_rot, box_axis, math.pi/4)
43 
44 hole = geompy.MakeCut(cylinder, box)
45 
46 plane_trim = 2000
47 
48 plane_a = geompy.MakePlane(base, geompy.MakeVectorDXDYDZ(1, 0, 0), plane_trim)
49 plane_b = geompy.MakePlane(base, geompy.MakeVectorDXDYDZ(0, 1, 0), plane_trim)
50 
51 blocks_part = geompy.MakePartition([hole], [plane_a, plane_b], [], [], geompy.ShapeType["SOLID"])
52 blocks_list = [box] + geompy.SubShapeAll(blocks_part, geompy.ShapeType["SOLID"])
53 blocks_all = geompy.MakeCompound(blocks_list)
54 blocks = geompy.MakeGlueFaces(blocks_all, 0.0001)
55 
56 geompy.addToStudy(blocks, "cylinder:blocks")
57 
58 # Build geometric groups
59 # ----------------------
60 
61 def group(name, shape, type, base=None, direction=None):
62  t = geompy.ShapeType[type]
63  g = geompy.CreateGroup(shape, t)
64 
65  geompy.addToStudyInFather(shape, g, name)
66 
67  if base!=None:
68  l = geompy.GetShapesOnPlaneWithLocationIDs(shape, t, direction, base, GEOM.ST_ON)
69  geompy.UnionIDs(g, l)
70 
71  return g
72 
73 group_a = group("baseA", blocks, "FACE", base, direction)
74 
75 base_b = geompy.MakeVertex(0, 0, height)
76 group_b = group("baseB", blocks, "FACE", base_b, direction)
77 
78 group_1 = group("limit", blocks, "SOLID")
79 group_1_all = geompy.SubShapeAllIDs(blocks, geompy.ShapeType["SOLID"])
80 geompy.UnionIDs(group_1, group_1_all)
81 group_1_box = geompy.GetBlockNearPoint(blocks, base)
82 geompy.DifferenceList(group_1, [group_1_box])
83 
84 # Mesh the blocks with hexahedral
85 # -------------------------------
86 
87 smesh.SetCurrentStudy(salome.myStudy)
88 
89 def discretize(x, y, z, nbSeg, shape=blocks):
90  vert = geompy.MakeVertex( x, y, z )
91  edge = geompy.GetEdgeNearPoint( shape, vert )
92  algo = hexa.Segment( edge )
93  algo.NumberOfSegments( nbSeg )
94  algo.Propagation()
95 
96 hexa = smesh.Mesh(blocks)
97 
98 hexa_1d = hexa.Segment()
99 hexa_1d.NumberOfSegments(1)
100 
101 discretize(+radius , +radius, 0, 5)
102 discretize(-radius , +radius, 0, 8)
103 discretize((radius+size)/2, 0, 0, 10)
104 discretize( +radius, 0, height/2, 20)
105 
106 hexa.Quadrangle()
107 hexa.Hexahedron()
108 
109 hexa.Compute()
110 
111 hexa.Group(group_a)
112 hexa.Group(group_b)
113 hexa.Group(group_1)

Download this script

mesh_cylinder_hexa.png


Building a compound of meshes

1 # Building a compound of meshes
2 
3 import salome
4 salome.salome_init()
5 import GEOM
6 from salome.geom import geomBuilder
7 geompy = geomBuilder.New(salome.myStudy)
8 
9 import SMESH, SALOMEDS
10 from salome.smesh import smeshBuilder
11 smesh = smeshBuilder.New(salome.myStudy)
12 
13 ## create a bottom box
14 Box_inf = geompy.MakeBox(0., 0., 0., 200., 200., 50.)
15 
16 # get a top face
17 Psup1=geompy.MakeVertex(100., 100., 50.)
18 Fsup1=geompy.GetFaceNearPoint(Box_inf, Psup1)
19 # get a bottom face
20 Pinf1=geompy.MakeVertex(100., 100., 0.)
21 Finf1=geompy.GetFaceNearPoint(Box_inf, Pinf1)
22 
23 ## create a top box
24 Box_sup = geompy.MakeBox(100., 100., 50., 200., 200., 100.)
25 
26 # get a top face
27 Psup2=geompy.MakeVertex(150., 150., 100.)
28 Fsup2=geompy.GetFaceNearPoint(Box_sup, Psup2)
29 # get a bottom face
30 Pinf2=geompy.MakeVertex(150., 150., 50.)
31 Finf2=geompy.GetFaceNearPoint(Box_sup, Pinf2)
32 
33 ## Publish in the study
34 geompy.addToStudy(Box_inf, "Box_inf")
35 geompy.addToStudyInFather(Box_inf, Fsup1, "Fsup")
36 geompy.addToStudyInFather(Box_inf, Finf1, "Finf")
37 
38 geompy.addToStudy(Box_sup, "Box_sup")
39 geompy.addToStudyInFather(Box_sup, Fsup2, "Fsup")
40 geompy.addToStudyInFather(Box_sup, Finf2, "Finf")
41 
42 smesh.SetCurrentStudy(salome.myStudy)
43 
44 ## create a bottom mesh
45 Mesh_inf = smesh.Mesh(Box_inf, "Mesh_inf")
46 algo1D_1=Mesh_inf.Segment()
47 algo1D_1.NumberOfSegments(10)
48 algo2D_1=Mesh_inf.Quadrangle()
49 algo3D_1=Mesh_inf.Hexahedron()
50 Mesh_inf.Compute()
51 
52 # create a group on the top face
53 Gsup1=Mesh_inf.Group(Fsup1, "Sup")
54 # create a group on the bottom face
55 Ginf1=Mesh_inf.Group(Finf1, "Inf")
56 
57 ## create a top mesh
58 Mesh_sup = smesh.Mesh(Box_sup, "Mesh_sup")
59 algo1D_2=Mesh_sup.Segment()
60 algo1D_2.NumberOfSegments(5)
61 algo2D_2=Mesh_sup.Quadrangle()
62 algo3D_2=Mesh_sup.Hexahedron()
63 Mesh_sup.Compute()
64 
65 # create a group on the top face
66 Gsup2=Mesh_sup.Group(Fsup2, "Sup")
67 # create a group on the bottom face
68 Ginf2=Mesh_sup.Group(Finf2, "Inf")
69 
70 ## create compounds
71 # create a compound of two meshes with renaming namesake groups and
72 # merging elements with the given tolerance
73 Compound1 = smesh.Concatenate([Mesh_inf, Mesh_sup], 0, 1, 1e-05,
74  name='Compound with RenamedGrps and MergeElems')
75 # create a compound of two meshes with uniting namesake groups and
76 # creating groups of all elements
77 Compound2 = smesh.Concatenate([Mesh_inf, Mesh_sup], 1, 0, 1e-05, True,
78  name='Compound with UniteGrps and GrpsOfAllElems')
79 
80 if salome.sg.hasDesktop():
81  salome.sg.updateObjBrowser(True)

Download this script


Mesh Copying

1 # Mesh Copying
2 
3 import salome
4 salome.salome_init()
5 import GEOM
6 from salome.geom import geomBuilder
7 geompy = geomBuilder.New(salome.myStudy)
8 
9 import SMESH, SALOMEDS
10 from salome.smesh import smeshBuilder
11 smesh = smeshBuilder.New(salome.myStudy)
12 
13 # make geometry of a box
14 box = geompy.MakeBoxDXDYDZ(100,100,100)
15 face = geompy.SubShapeAllSorted(box, geompy.ShapeType["FACE"])[0]
16 
17 # generate a prismatic 3D mesh
18 mesh = smesh.Mesh(box)
19 localAlgo = mesh.Triangle(face)
20 mesh.AutomaticHexahedralization()
21 
22 # objects to copy
23 fGroup = mesh.GroupOnGeom( face, "2D on face")
24 nGroup = mesh.GroupOnGeom( face, "nodes on face", SMESH.NODE)
25 subMesh = localAlgo.GetSubMesh()
26 
27 # make a new mesh by copying different parts of the mesh
28 
29 # 1. copy the whole mesh
30 newMesh = smesh.CopyMesh( mesh, "whole mesh copy")
31 
32 # 2. copy a group of 2D elements along with groups
33 newMesh = smesh.CopyMesh( fGroup, "face group copy with groups",toCopyGroups=True)
34 
35 # 3. copy a group of nodes
36 newMesh = smesh.CopyMesh( nGroup, "node group copy")
37 
38 # 4. copy some faces
39 faceIds = fGroup.GetIDs()[-10:]
40 newMesh = smesh.CopyMesh( mesh.GetIDSource( faceIds, SMESH.FACE ), "some faces copy")
41 
42 # 5. copy some nodes
43 nodeIds = nGroup.GetIDs()[-10:]
44 newMesh = smesh.CopyMesh( mesh.GetIDSource( nodeIds, SMESH.NODE), "some nodes copy")
45 
46 # 6. copy a sub-mesh
47 newMesh = smesh.CopyMesh( subMesh, "sub-mesh copy" )

Download this script