Profiling the code

Using PatchMesher to model a quarter of the plate

# sphinx_gallery_thumbnail_path = '_static/profiler.png'

SPARSE = False

import math
import sys
import numpy as np

from femedu.examples import Example

from femedu.domain import System, Node
from femedu.solver import NewtonRaphsonSolver, SparseSolver
from femedu.elements.linear import Triangle
from femedu.materials import PlaneStress
from femedu.mesher import *


class ExamplePlate14(Example):

    def problem(self):
        # ========== setting mesh parameters ==============

        Nx = 60        # number of elements in the mesh
        Ny = 40        # number of elements in the mesh

        Lx = 120.0    # length of plate in the x-direction
        Ly =  80.0    # length of plate in the y-direction
        R  = Ly / 2.

        # ========== setting material parameters ==============

        params = dict(
            E  = 200.,      # Young's modulus
            nu = 0.450,     # Poisson's ratio
            t  = 1.00       # thickness of the plate
        )

        # ========== setting load parameters ==============

        px  = 20.0         # uniform load normal to x=const
        py  =  0.0         # uniform load normal to y=const
        pxy =  0.0         # uniform shear load on x=const and y=const

        # ========== setting analysis parameters ==============

        target_load_level = 1.00     # reference load
        max_steps = 2                # number of load steps: 2 -> [0.0, 1.0]

        # define a list of target load levels
        load_levels = np.linspace(0, target_load_level, max_steps)

        #
        # ==== Build the system model ====
        #

        model = System()
        if SPARSE:
            model.setSolver(SparseSolver())
        else:
            model.setSolver(NewtonRaphsonSolver())

        # create nodes

        #  3---------2
        #  |         |
        #  |         |
        #  |         |
        #  1---------1

        pts = (
            ( 0, 0),
            (Lx, 0),
            (Lx, Ly),
            (0, Ly),
        )

        mesher = PatchMesher(model, pts[0], pts[1], pts[2], pts[3])
        nodes, elements = mesher.triangleMesh(Nx, Ny, Triangle, PlaneStress(params))

        # define support(s)

        ## find nodes at y==0 and x==0

        for node in nodes:
            X = node.getPos()
            if math.isclose(X[0], 0.0):
                node.fixDOF('ux')    # horizontal support left side
            if math.isclose(X[1], 0.0):
                node.fixDOF('uy')    # vertical support at y==0

        # ==== build the reference load ====

        # the section at the right end
        for elem, face in model.findFacesAlongLine((Lx, 0.0), (0.0, 1.0), orientation=+1):
            print('+', elem.getID(), face.id, ":", face.area)
            face.setLoad(px, pxy)

        model.plot(factor=0, title="undeformed system", filename="plate14_undeformed.png", show_bc=1, show_loads=1)

        model.setLoadFactor(1.0)
        model.solve()

        #model.plot(factor=1., filename="plate14_deformed.png")

        #model.solver.showKt(filename="plate14_spy_Kt.png")
        #np.save("plate14_Kt.npy",model.solver.Kt)

Run the example by creating an instance of the problem and executing it by calling Example.run()

This time, we are running the example in the profiler, writing profiling data to file.

    import cProfile

    ex = ExamplePlate14()

    if SPARSE:
        cProfile.run('ex.run()','profile_data_sparse.txt')
    else:
        cProfile.run('ex.run()','profile_data_full.txt')
undeformed system
+ Elem_1082 1082.2 : [[2 0]]
+ Elem_1202 1202.2 : [[2 0]]
+ Elem_1322 1322.2 : [[2 0]]
+ Elem_1442 1442.2 : [[2 0]]
+ Elem_1562 1562.2 : [[2 0]]
+ Elem_1682 1682.2 : [[2 0]]
+ Elem_1802 1802.2 : [[2 0]]
+ Elem_1922 1922.2 : [[2 0]]
+ Elem_2042 2042.2 : [[2 0]]
+ Elem_2162 2162.2 : [[2 0]]
+ Elem_2282 2282.2 : [[2 0]]
+ Elem_2402 2402.2 : [[2 0]]
+ Elem_2522 2522.2 : [[2 0]]
+ Elem_2642 2642.2 : [[2 0]]
+ Elem_2762 2762.2 : [[2 0]]
+ Elem_2882 2882.2 : [[2 0]]
+ Elem_3002 3002.2 : [[2 0]]
+ Elem_3122 3122.2 : [[2 0]]
+ Elem_3242 3242.2 : [[2 0]]
+ Elem_3362 3362.2 : [[2 0]]
+ Elem_3482 3482.2 : [[2 0]]
+ Elem_3602 3602.2 : [[2 0]]
+ Elem_3722 3722.2 : [[2 0]]
+ Elem_3842 3842.2 : [[2 -1.42109e-14]]
+ Elem_3962 3962.2 : [[2 1.42109e-14]]
+ Elem_4082 4082.2 : [[2 0]]
+ Elem_4202 4202.2 : [[2 0]]
+ Elem_4322 4322.2 : [[2 0]]
+ Elem_4442 4442.2 : [[2 0]]
+ Elem_4562 4562.2 : [[2 0]]
+ Elem_4682 4682.2 : [[2 0]]
+ Elem_4802 4802.2 : [[2 0]]
+ Elem_4922 4922.2 : [[2 1.42109e-14]]
+ Elem_5042 5042.2 : [[2 -1.42109e-14]]
+ Elem_5162 5162.2 : [[2 0]]
+ Elem_5282 5282.2 : [[2 0]]
+ Elem_5402 5402.2 : [[2 0]]
+ Elem_5522 5522.2 : [[2 0]]
+ Elem_5642 5642.2 : [[2 0]]
+ Elem_5762 5762.2 : [[2 0]]
+

Now it’s time to process the profiling data

    import pstats
    from pstats import SortKey

    if SPARSE:
        p = pstats.Stats('profile_data_sparse.txt')
        p.strip_dirs() #.sort_stats(-1).print_stats()
        p.sort_stats(SortKey.NAME)
        #p.print_stats()

        p.sort_stats(SortKey.CUMULATIVE).print_stats(20)
        p.sort_stats(SortKey.TIME).print_stats(20)

    else:
        p = pstats.Stats('profile_data_full.txt')
        p.strip_dirs() #.sort_stats(-1).print_stats()
        p.sort_stats(SortKey.NAME)
        #p.print_stats()

        p.sort_stats(SortKey.CUMULATIVE).print_stats(20)
        p.sort_stats(SortKey.TIME).print_stats(20)
Thu Feb 20 17:24:57 2025    profile_data_full.txt

         21646815 function calls (20989348 primitive calls) in 8.010 seconds

   Ordered by: cumulative time
   List reduced from 1350 to 20 due to restriction <20>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        5    0.000    0.000    4.778    0.956 NewtonRaphsonSolver.py:111(assemble)
        5    0.405    0.081    4.778    0.956 Solver.py:166(assemble)
        1    0.000    0.000    4.624    4.624 System.py:504(solve)
        1    0.000    0.000    4.624    4.624 NewtonRaphsonSolver.py:13(solve)
     35/3    0.006    0.000    3.247    1.082 text.py:358(_get_layout)
    43200    1.201    0.000    2.903    0.000 Triangle.py:80(updateState)
     81/7    0.000    0.000    2.274    0.325 text.py:65(_get_text_metrics_with_cache)
      9/4    0.000    0.000    2.274    0.569 text.py:73(_get_text_metrics_with_cache_impl)
     10/4    0.008    0.001    2.273    0.568 backend_agg.py:206(get_text_width_height_descent)
        2    0.000    0.000    2.147    1.073 Solver.py:395(checkResiduum)
    24000    0.052    0.000    1.809    0.000 Element.py:271(getForce)
    19200    0.072    0.000    1.770    0.000 Element.py:348(getStiffness)
     49/2    0.000    0.000    1.754    0.877 text.py:926(get_window_extent)
    72000    0.270    0.000    1.158    0.000 Triangle.py:159(computeSurfaceLoads)
663450/182418    0.375    0.000    0.873    0.000 copy.py:119(deepcopy)
     4902    0.009    0.000    0.852    0.000 _axes.py:1532(plot)
   216000    0.312    0.000    0.682    0.000 Face2D.py:54(computeNodalForces)
    28800    0.046    0.000    0.656    0.000 Element.py:286(getLoad)
    14706    0.036    0.000    0.611    0.000 lines.py:744(draw)
        1    0.036    0.036    0.540    0.540 Solver.py:454(getNodalReactions)


Thu Feb 20 17:24:57 2025    profile_data_full.txt

         21646815 function calls (20989348 primitive calls) in 8.010 seconds

   Ordered by: internal time
   List reduced from 1350 to 20 due to restriction <20>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    43200    1.201    0.000    2.903    0.000 Triangle.py:80(updateState)
        5    0.405    0.081    4.778    0.956 Solver.py:166(assemble)
663450/182418    0.375    0.000    0.873    0.000 copy.py:119(deepcopy)
   302400    0.340    0.000    0.431    0.000 numeric.py:876(outer)
        1    0.327    0.327    0.327    0.327 _linalg.py:320(solve)
  1150018    0.320    0.000    0.320    0.000 {built-in method numpy.array}
   216000    0.312    0.000    0.682    0.000 Face2D.py:54(computeNodalForces)
    72000    0.270    0.000    1.158    0.000 Triangle.py:159(computeSurfaceLoads)
     9806    0.248    0.000    0.406    0.000 backend_agg.py:93(draw_path)
   192082    0.206    0.000    0.468    0.000 Node.py:455(getDeformedPos)
    43201    0.192    0.000    0.270    0.000 PlaneStress.py:28(updateState)
   192490    0.161    0.000    0.251    0.000 Node.py:341(getDisp)
   244800    0.158    0.000    0.210    0.000 Node.py:506(getIdx4Element)
   218462    0.143    0.000    0.193    0.000 numeric.py:64(zeros_like)
  1784484    0.112    0.000    0.112    0.000 {method 'append' of 'list' objects}
   470592    0.111    0.000    0.158    0.000 copy.py:232(_keep_alive)
68760/34414    0.087    0.000    0.176    0.000 transforms.py:2431(get_affine)
    39338    0.084    0.000    0.094    0.000 __init__.py:65(check_isinstance)
  1300467    0.082    0.000    0.094    0.000 {built-in method builtins.isinstance}
    14400    0.076    0.000    0.076    0.000 {method 'index' of 'list' objects}

Total running time of the script: (0 minutes 7.957 seconds)

Gallery generated by Sphinx-Gallery