<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Kulak & Grondin Example 8.2
This example is from "Limit States Design in Structural Steel", Ninth Edition, CISC, by Kulak and Grondin.
This example is slightly modified in order to compare the results with 
that obtained using
the method of slope-deflection.  The modifications
to the model are
Step1:  The notional lateral loads of 6.9 kN at node H and 8.4 kN at node G
are added as before.
Step2:  Compare with results from slope-deflection
Step3:  % Difference in End Moments
Step4:  Max. difference is 0.000006%, which is quite good.
<ASSISTANT_TASK:>
Python Code:
from Frame2D import Frame2D
from IPython import display
display.Image('data/KG82.d/KG82a.jpg')
Explanation: Kulak & Grondin Example 8.2
This example is from "Limit States Design in Structural Steel", Ninth Edition, CISC, by Kulak and Grondin.
This example is slightly modified in order to compare the results with 
that obtained using
the method of slope-deflection.  The modifications
to the model are:
* a pin is inserted at the top of columns JK and IG, with the result that column stacks JKL and IGH
offer no lateral resistance (in the original K&G example, the columns are continuous and there is a very
small horizontal reaction at the base of those two columns).
* the cross-sectional areas of all members are made very large so as to make axial
changes in length neglible.
End of explanation
frame = Frame2D('KG82sd')
frame.input_all()
RS = frame.solve('all')
frame.write_results(frame.dsname,RS)
frame.print_input()
frame.print_results(RS)
Explanation: The notional lateral loads of 6.9 kN at node H and 8.4 kN at node G
are added as before.
End of explanation
import pandas as pd
BM = [('AB', -49.9080183705027, 47.4941396356060),   # results from method of slope deflection
     ('BC', 250.526060428376, 252.096857589821),
     ('DE', -189.782099213905, -232.254022051198),
     ('EF', -290.011616822927, -333.061301195269),
     ('BE', -298.020200063982, 522.265638874126),
     ('CF', -252.096857589821, 333.061301195269)]
SD = pd.DataFrame({m:{'MZJ':-a,'MZK':-b} for m,a,b in BM}).T
SD
# get our member end forces for the same members
HERE = pd.DataFrame([(m.id,ef.m2/1e6,ef.m5/1e6) 
                     for m,ef in RS.member_efs.items()],columns=['ID','MZJ','MZK']).set_index(['ID'])
HERE = HERE.loc[SD.index]
HERE
Explanation: Compare with results from slope-deflection
End of explanation
pd = (100*(SD-HERE)/HERE).round(6)
pd
Explanation: % Difference in End Moments
End of explanation
pd.abs().max()
Explanation: Max. difference is 0.000006%, which is quite good.
End of explanation
<END_TASK>