def createGridScene(rootNode, startPoint, endPoint, numX, numY, numZ,
                    totalMass, stiffnessValue, dampingRatio):

    # The graph root node
    rootNode.setGravity(Sofa.Vector3(0, -10, 0))
    rootNode.dt = 0.01
    rootNode.createObject(
        'VisualStyle',
        displayFlags=
        'hideVisual showBehavior hideCollision showMapping hideOptions')

    simulatedScene = rootNode.createChild('simulatedScene')

    eulerImplicitSolver = simulatedScene.createObject('EulerImplicitSolver')
    cgLinearSolver = simulatedScene.createObject('CGLinearSolver')

    # The rigid object
    rigidNode = simulatedScene.createChild('rigidNode')
    rigid_dof = rigidNode.createObject('MechanicalObject',
                                       template='Rigid',
                                       name='rigidNode_dof')
    rigid_mass = rigidNode.createObject('UniformMass',
                                        template='Rigid',
                                        name='rigidNode_mass')
    rigid_fixedConstraint = rigidNode.createObject(
        'FixedConstraint', template='Rigid', name='rigidNode_fixedConstraint')

    # Particles mapped to the rigid object
    mappedParticles = rigidNode.createChild('mappedParticles')
    mappedParticles_dof = mappedParticles.createObject(
        'MechanicalObject', name='mappedParticles_dof')
    mappedParticles_mapping = mappedParticles.createObject(
        'RigidMapping',
        template='Rigid',
        name='mappedParticles_mapping',
        input='@./../rigidNode_dof',
        output='@./mappedParticles_dof')

    #    // The independent particles
    independentParticles = simulatedScene.createChild('independentParticles')
    independentParticles_dof = independentParticles.createObject(
        'MechanicalObject', name='independentParticles_dof')

    #    // The deformable grid, connected to its 2 parents using a MultiMapping
    deformableGrid = independentParticles.createChild(
        'deformableGrid')  # first parent
    mappedParticles.addChild(deformableGrid)  # second parent

    deformableGrid_grid = deformableGrid.createObject(
        'RegularGridTopology', name='deformableGrid_grid')
    deformableGrid_grid.setNumVertices(numX, numY, numZ)
    deformableGrid_grid.setPos(startPoint.x, endPoint.x, startPoint.y,
                               endPoint.y, startPoint.z, endPoint.z)

    deformableGrid_dof = deformableGrid.createObject('MechanicalObject',
                                                     name='deformableGrid_dof')
    #    deformableGrid_mapping = mappedParticles.createObject('SubsetMultiMapping', template='Vec3d,Vec3d', name='mapping', input='@../../simulatedScene/independentParticles/independentParticles_dof @./mappedParticles_dof', output='@../../simulatedScene/independentParticles/deformableGrid/deformableGrid_dof')
    deformableGrid_mapping = deformableGrid.createObject(
        'SubsetMultiMapping',
        template='Vec3d,Vec3d',
        name='mapping',
        input=
        '@/simulatedScene/independentParticles/independentParticles_dof @/simulatedScene/rigidNode/mappedParticles/mappedParticles_dof',
        output='@./deformableGrid_dof')

    mass = deformableGrid.createObject('UniformMass',
                                       template='Vec3d',
                                       name='deformableGrid_mass')
    mass.mass = totalMass / (numX * numY * numZ)

    hexaFem = deformableGrid.createObject('HexahedronFEMForceField',
                                          template='Vec3d',
                                          name='deformableGrid_hexaFEM')
    hexaFem.youngModulus = 1000
    hexaFem.poissonRatio = 0.4

    #    // ======  Set up the multimapping and its parents, based on its child
    deformableGrid_grid.init(
    )  # initialize the grid, so that the particles are located in space
    deformableGrid_dof.init()  # create the state vectors
    xgrid = deformableGrid_dof.position  #    xgrid = deformableGrid_dof.readPositions()   #    cerr<<"xgrid = " << xgrid << endl;
    # xgrid is not the positions vector of the dof, but a copy of it

    #    // create the rigid frames and their bounding boxes
    numRigid = 2
    boxes = []  #    vector<BoundingBox> boxes(numRigid);
    indices = [
        [], []
    ]  #    vector< vector<unsigned> > indices(numRigid); // indices of the particles in each box
    eps = (endPoint.x - startPoint.x) / (numX * 2.0)

    #    // first box, x=xmin
    boxes.append(
        BoundingBox(
            Sofa.Vector3(startPoint.x - eps, startPoint.y - eps,
                         startPoint.z - eps),
            Sofa.Vector3(startPoint.x + eps, endPoint.y + eps,
                         endPoint.z + eps)))

    #    // second box, x=xmax
    boxes.append(
        BoundingBox(
            Sofa.Vector3(endPoint.x - eps, startPoint.y - eps,
                         startPoint.z - eps),
            Sofa.Vector3(endPoint.x + eps, endPoint.y + eps,
                         endPoint.z + eps)))

    rigid_dof.resize(numRigid)
    #    MechanicalObjectRigid3d::WriteVecCoord xrigid = rigid_dof->writePositions();
    # for xrigid, we create a list of 7-coords lists (position+orientation), then we will copy it in rigid_dof.position when we are done
    xrigid = []
    xrigid.append([
        startPoint.x, 0.5 * (startPoint.y + endPoint.y),
        0.5 * (startPoint.z + endPoint.z), 0, 0, 0, 1
    ])
    xrigid.append([
        endPoint.x, 0.5 * (startPoint.y + endPoint.y),
        0.5 * (startPoint.z + endPoint.z), 0, 0, 0, 1
    ])
    rigid_dof.position = xrigid

    #    // find the particles in each box
    isFree = [True] * len(xgrid)
    numMapped = 0
    for i in range(len(xgrid)):
        for b in range(numRigid):
            if isFree[i] and boxes[b].contains(xgrid[i]):
                indices[b].append(i)  # associate the particle with the box
                isFree[i] = False
                numMapped = numMapped + 1

#    // distribution of the grid particles to the different parents (independent particle or solids.
    parentParticles = [None] * len(
        xgrid
    )  #    vector< pair<MechanicalObject3d*,unsigned> > parentParticles(xgrid.size());

    #    // Copy the independent particles to their parent DOF
    independentParticles_dof.resize(numX * numY * numZ - numMapped)
    xindependent = independentParticles_dof.position  #    MechanicalObject3::WriteVecCoord xindependent = independentParticles_dof->writePositions(); // parent positions
    independentIndex = 0
    for i in range(len(xgrid)):
        if isFree[i]:
            parentParticles[i] = [independentParticles_dof, independentIndex]
            xindependent[independentIndex] = xgrid[i]
            independentIndex = independentIndex + 1
    independentParticles_dof.position = xindependent

    #    // Mapped particles. The RigidMapping requires to cluster the particles based on their parent frame.
    mappedParticles_dof.resize(numMapped)
    #    print 'numMapped='+str(numMapped)
    xmapped = mappedParticles_dof.position  #    MechanicalObject3::WriteVecCoord xmapped = mappedParticles_dof->writePositions(); // parent positions
    print 'xmapped size = ' + str(len(xmapped))
    mappedParticles_mapping.globalToLocalCoords = True  # to define the mapped positions in world coordinates
    pointsPerFrame = [
    ]  #    vector<unsigned>* pointsPerFrame = mappedParticles_mapping->pointsPerFrame.beginEdit(); // to set how many particles are attached to each frame
    mappedIndex = 0
    print 'len(indices)=' + str(len(indices))
    #    print 'indices='+str(indices)
    for ind in indices:
        print 'len(ind)=' + str(len(ind))
        pointsPerFrame.append(
            len(ind)
        )  # Tell the mapping the number of points associated with this frame. One box per frame
        for i in ind:
            print 'i=' + str(i) + '    mappedIndex=' + str(mappedIndex)
            parentParticles[i] = [mappedParticles_dof, mappedIndex]
            #            print 'xgrid[i]'+str(xgrid[i])
            xmapped[mappedIndex] = xgrid[i]
            mappedIndex = mappedIndex + 1
    mappedParticles_dof.position = xmapped
    print 'repartition=' + str(mappedParticles_mapping.repartition)
    mappedParticles_mapping.findData('repartition').setSize(
        len(pointsPerFrame))
    mappedParticles_mapping.repartition = pointsPerFrame

    #    // Declare all the particles to the multimapping
    for pp in parentParticles:
        deformableGrid_mapping.addPoint(pp[0], pp[1])
def createScene(rootNode):
    createGridScene(rootNode, Sofa.Vector3(0, 0, 0), Sofa.Vector3(5, 1, 1), 6,
                    2, 2, 1.0, 100.0, 0.0)
    return rootNode