変位型のFEMでは,テンソル量としての要素内応力を求める.一方,HPMでは,FEMと同様,領域内においてテンソル量としての応力が求まるとともに,RBSMと同様,隣接する2領域間の境界辺上における単位面積当りの表面力を求めることができる.本節では,HPMの特徴でもある,表面力を求めるプログラムについて述べる.
図6.1 は増分表面力計算の流れを示したものである.表面力は,ペナルティ関数が設定される小領域の境界辺で求められるため,全処理に渡るペナルティ数に関するループを図のように設ける.本来の表面力計算に関する部分は(*3)に示す点線で囲まれた部分であるが,同時に除荷や負荷の判定も行う.山田の方法による荷重増分法を用いて非線形計算を行う場合には,このような除荷や負荷の判定を行つておく必要がある.
$\hspace{3em}$図6.1 増分表面力の計算
プログラムを簡単にし,理解しやすいようにするなら,(*3)に示す部分を取り出し,増分表面力計算の部分と除荷,負荷の部分を別なサブルーチンにより処理した方がよいが,ここでは,計算の効率化を考え,同一サブルーチン内で処理している.これは,除荷や負荷が生じた場合,今回の荷重増分計算を無効とし,剛性を変えて再計算するためである.本サンプルプログラムでは前回のペナルティ辺の状態が降伏状態で今回の増分計算により除荷が発生したならば,剛性を弾性状態に変えて再計算を行つている.また,除荷状態から負荷状態に変われば剛性を降伏状態に変えて再計算を行う.本書では簡単な降伏条件を用いているが,さらに複雜な降伏条件を用いるなら,当然この判定や剛性の考え方は変わってくる.除荷,負荷については次節にゆずるとし,ここでは,おおまかな計算の流れをもう少し説明する.
(*1)に示す判定文では増分計算あるいは再計算過程において除荷あるいは負荷が発生したペナルティ辺が存在するか否かのチェックを行つている.もし,一箇所以上のペナルティ辺に除荷もしくは負荷が発生していたなら,以後,降伏しているペナルティ辺についてのみ $\mu$ 計算のための増分計算をおこない,再計算を行う準備を行う.この降伏の判定文が(*2)である.除荷,負荷が発生していなければ通常の(*3)に示す増分計算を行う.
以上の処理は,
プログラム6.1 に示す
サブルーチン(SpringStress) で行っている.
プログラム6.1 増分表面力計算のコントロール(SpringStress)
1119 !--------------------------------------------------------------------------
1120 SUBROUTINE SpringStress( Node, Element, Material, Spring, Line, jramc, jramd )
1121
1122 TYPE(typeNode), INTENT(IN) :: Node
1123 TYPE(typeElement), INTENT(IN) :: Element
1124 TYPE(typeMaterial), INTENT(IN) :: Material
1125 TYPE(typeSpring), INTENT(INOUT) :: Spring
1126 TYPE(typeNumInteg), INTENT(IN) :: Line
1127 INTEGER, INTENT(INOUT) :: jramc
1128 INTEGER, INTENT(INOUT) :: jramd
1129 REAL(8) :: sig(2,3),D(2,2),ww
1130 INTEGER :: is,ip,jbit,i,j
1131
1132 jramd = 0
1133
1134 DO is = 1, Spring%no
1135 IF(jramd == 1 .AND. Spring%flag(is) == 0) CYCLE
1136 IF(jramd == 1 .AND. Spring%flag(is) == -2) CYCLE
1137 CALL Strain(is,Node,Element,Spring,Line )
1138 CALL formSpring(is,Element,Material,Spring,D)
1139 D = D*Spring%penalty
1140 DO ip = 1, Line%no
1141 DO i = 1, 2
1142 ww = 0.0
1143 DO j = 1, 2
1144 ww = ww + D(i,j)*Spring%dstrain(j,is,ip)
1145 END DO
1146 sig(i,ip) = ww
1147 END DO
1148 END DO
1149 DO i = 1, 2
1150 ww = 0.D0
1151 DO ip = 1, Line%no
1152 ww = ww + sig(i,ip)*Line%weight(ip)
1153 END DO
1154 Spring%Dstress(i,is) = 0.5D0*ww
1155 END DO
1156 IF(jramc .LT. 2) THEN
1157 IF(Spring%flag(is) == 1 .OR. Spring%flag(is) == 2) THEN
1158 jbit = 0
1159 IF(Spring%flag(is) == 2) jbit = 1
1160 CALL Unload(is,Element,Material,Spring,D,jramd,jbit)
1161 END IF
1162 END IF
1163 END DO
1164 jramc = jramc + 1
1165 END SUBROUTINE SpringStress
変数(jramd) は通常0であり,いずれかのペナルティ辺に除荷や負荷が発生すると1になる.この変数によって,
図6.1 に示す(*1)の判定を行う.また,1158行に示す
変数(jbit) は現在のペナルティ辺の状態を示すフラッグで,0の場合は降伏状態を,1のときは除荷状態を表している.
1056行及び1164行に示す
変数(jramc) は再計算回数を制限するカウンタである.数値計算上の誤差などの関係により,同じペナルティ辺において除荷と負荷が繰り返し発生することがある.このような場合,1056行に示すよう,再計算回数に関する制限を設けておかなければプログラムが暴走する可能性もある.本サンプル・プログラムでは再計算回数を2回までに制限している.したがって,前回降伏しているペナルティ辺については繰り返し状態になった場合,降伏状態のまま変化がないものとし,負荷の場合は,やはり負荷のままであると考えている.もちろん,この点に関しては,計算上のテクニックであるから変更しても差し支えない.
次に,
図6.1 の点線で囲まれた部分について考えてみよう.詳細は後述するが,1137行では2領域間の相対変位を隣接する領域の垂線の高さの和 $h=h_1+h_2$ で除した仮想ひずみ増分 $\Delta \varepsilon_i$ を計算する
副プログラム(Starain) を呼び出している.なお,本サンプル・プログラムでは,ペナルティ係数行列を求める際の積分点で相対変位を求めており,$\Delta \boldsymbol{\varepsilon}_i$ の $i$ は1~3の積分点番号を意味している.
一方,1138行では,
プログラム5.5 で示したペナルティ辺の構成行列 $\boldsymbol{D}$ を求める
副プログラム(formSpring) 呼び出している.この構成行列は垂線の高さで除していない行列となっている.したがって,1144行のように,$\boldsymbol{D}$ と $\Delta \boldsymbol{\varepsilon}_i$ の積が増分表面力 $\Delta \boldsymbol{\lambda}_i$ となる.
この増分表面力 $\Delta \boldsymbol{\lambda}_i$ も,積分点毎の仮想ひずみから求めるため,積分点毎の値となる.この表面力を利用して積分点毎に破壊の判定を行っても良いが,本サンプルプログラムでは応力評価を1点で行い破壊判定をする.そのため,1149行~1155行に示すように,数値積分の重み $w_i$ を用いた重み付き平均によって,以下のように応力を評価している.
\[
{\rm (6.1)}
\Delta \boldsymbol{\lambda}
=
\sum_{i=1}^3 \left( w_i \Delta \boldsymbol{\lambda}_i \right)
/ \sum_{i=1}^3 w_i
\]
さて,積分点毎の仮想ひずみの計算は
\[
{\rm (6.2)}
\Delta \boldsymbol{\varepsilon}_i
=
\frac{1}{h} \boldsymbol{B}_i \cdot \Delta \boldsymbol{u}
\]
で計算する.ここで,$\Delta \boldsymbol{u}$ はペナルティ辺に関係する隣接領域の自由度を並べたベクトルである.また,$\boldsymbol{B}_i$ は,
プログラム5.3 に掲載した
副プログラム(formB) で作成される積分点 $i$ におけるひずみ-変位関係の行列である.具体的なプログラムを
プログラム6.2 に示す.
プログラム6.2 増分仮想ひずみの計算(Strain)
1166 !--------------------------------------------------------------------------
1167 SUBROUTINE Strain( is, Node, Element, Spring, Line )
1168
1169 INTEGER, INTENT(IN) :: is
1170 TYPE(typeNode), INTENT(IN) :: Node
1171 TYPE(typeElement), INTENT(IN) :: Element
1172 TYPE(typeNumInteg), INTENT(IN) :: Line
1173 TYPE(typeSpring), INTENT(INOUT) :: Spring
1174 REAL(8) :: uu(2*Element%dof),bb(2,2*Element%dof),h,ww
1175 INTEGER :: ie,ip,i,j,ii,jj
1176
1177 ii = 0
1178 DO i = 1, 2
1179 ie = Spring%element(i,is)
1180 DO j = 1, Element%dof
1181 ii = ii + 1
1182 jj = j + (ie-1)*Element%dof
1183 uu(ii) = Element%ddisp(jj)
1184 END DO
1185 END DO
1186 h = Spring%hline(1,is) + Spring%hline(2,is)
1187 DO ip = 1, Line%no
1188 CALL formB(is,ip,Node,Element,Spring,Line,bb)
1189 DO i = 1, 2
1190 ww = 0.D0
1191 DO j = 1, 2*Element%dof
1192 ww = ww + bb(i,j)*uu(j)
1193 END DO
1194 Spring%dstrain(i,is,ip) = ww/h
1195 END DO
1196 END DO
1197 END SUBROUTINE Strain
単位面積当りの表面力を計算する過程において,除荷,負荷の判定が必要であることを前節で述べた.本節ではこのことについて説明する.
完全弾塑性体を考えた場合,除荷は
図6.2 に示すような応力経路をたどる.
$\hspace{5em}$図6.2 除荷
このような除荷や負荷の判定を行うためには塑性仕事を計算し,その値によって判断しなければならない.本書では簡単のため,
3.2節 において説明したように,$\mu$ の計算によってそれを判定している.
図6.3 は除荷及び負荷過程に関する計算の流れを示したものである.
$\hspace{5em}$図6.3 除荷・負荷の判定フロー
判定を行うに際し,まず除荷状態もしくは負荷状態のばねに対し $\mu$ の計算を行う.もし,前回までのペナルティ辺の状態が降伏状態(
Spring%flag = 1 )であるなら除荷の可能性があり,また,除荷状態(
Spring%flag = 2 )であるなら負荷の可能性がある.そこで,初めに $\mu$ の計算を行い,現在のペナルティ辺の状態を調べて $\mu$ の正負により降伏フラッグを立て直す.ペナルティ辺の前回の状態が降伏状態なら $\mu \lt 0$ のとき除荷が発生し,降伏フラッグを
Spring%flag = 2 とする.また,除荷状態なら $\mu > 0$ のとき負荷となり,フラッグを
Spring%flag = 1 に変更する.
降伏状態 → $\mu \lt 0$ → 除荷発生 → Spring%flag = 2
除荷状態 → $\mu \gt 0$ → 負荷発生 → Spring%flag = 1
以上の判定をプログラム化したものが
プログラム6.3 である.
プログラム6.3 除荷・負荷の判定(Unload)
1198 !--------------------------------------------------------------------------
1199 SUBROUTINE Unload( is, Element, Material, Spring, D, jramd, jbit)
1200
1201 INTEGER, INTENT(IN) :: is
1202 TYPE(typeElement), INTENT(IN) :: Element
1203 TYPE(typeMaterial), INTENT(IN) :: Material
1204 TYPE(typeSpring), INTENT(INOUT) :: Spring
1205 REAL(8), INTENT(IN) :: D(:,:)
1206 INTEGER, INTENT(INOUT) :: jramd
1207 INTEGER, INTENT(IN) :: jbit
1208 REAL(8) :: lam
1209
1210 lam = Lambda(is,Element,Material,Spring,D)
1211 IF(jbit /= 1) THEN
1212 IF(lam < 0.D0) THEN
1213 Spring%flag(is) = 2
1214 jramd = 1
1215 END IF
1216 ELSE
1217 IF(lam > 0.D0) THEN
1218 Spring%flag(is) = 1
1219 jramd = 1
1220 END IF
1221 END IF
1222 END SUBROUTINE Unload
変数(jbit) は前節の表面力計算の項で説明したように,現在のペナルティ辺の状態が降伏状態なら0,除荷状態なら1の値を持つフラッグである.また,
変数(jramd) は通常0であり,除荷や負荷が発生すると1の値を持つ.
このサブルーチンに現れる $\mu$ の計算は
プログラム6.4 に示す
関数(Lambda) で行われる.$\mu$ の計算式は
3.2節 に示してある.1238行~1241行がMohr-Coulombの条件に関する $\mu$ を,1243行,1244行がvonMisesの条件に対する $\mu$ の計算を行つている箇所である.
プログラム6.4 $\mu$ の計算(Lambda)
1223 !--------------------------------------------------------------------------
1224 FUNCTION Lambda( is, Element, Material, Spring, D ) RESULT( lam )
1225
1226 INTEGER, INTENT(IN) :: is
1227 TYPE(typeElement), INTENT(IN) :: Element
1228 TYPE(typeMaterial), INTENT(IN) :: Material
1229 TYPE(typeSpring), INTENT(IN) :: Spring
1230 REAL(8), INTENT(IN) :: D(:,:)
1231 REAL(8) :: lam
1232 REAL(8) :: cm,phi,pt
1233 REAL(8) :: PAI = 3.141592654D0
1234
1235 lam = 0.0
1236
1237 IF(Element%type == 0) THEN
1238 CALL strength(is,Element,Material,Spring,cm,phi)
1239 pt = DTAN(phi*PAI/180.D0)
1240 lam = D(2,2)*Spring%stress(2,is)*Spring%dstrain(2,is,2) &
1241 + D(1,1)*(cm-Spring%stress(1,is)*pt)*pt*Spring%dstrain(1,is,2)
1242 ELSE
1243 lam = 2.0*D(2,2)*Spring%stress(2,is)*Spring%dstrain(2,is,2) &
1244 + 0.5*D(1,1)*Spring%stress(1,is)*Spring%dstrain(1,is,2)
1245 END IF
1246 END FUNCTION Lambda
Mohr-Coulombの条件の場合,$\mu$ の計算式に強度定数が含まれている.本書のサンプルプログラムでは,この強度定数に対しても垂線を重みとして平均値をとるよう考えている.この平均値の計算は
プログラム6.5 に示す
サブルーチン(strength) により行つている.
プログラム6.5 強度定数の平均値計算(strength)
1247 !--------------------------------------------------------------------------
1248 SUBROUTINE strength( is, Element, Material, Spring, cm, phi )
1249
1250 INTEGER, INTENT(IN) :: is
1251 TYPE(typeElement), INTENT(IN) :: Element
1252 TYPE(typeMaterial), INTENT(IN) :: Material
1253 TYPE(typeSpring), INTENT(IN) :: Spring
1254 REAL(8), INTENT(OUT) :: cm
1255 REAL(8), INTENT(OUT) :: phi
1256
1257 REAL(8) :: h
1258 INTEGER :: ie1,ie2,im1,im2
1259
1260 h = Spring%hline(1,is) + Spring%hline(2,is)
1261 ie1 = Spring%element(1,is)
1262 ie2 = Spring%element(2,is)
1263 im1 = Element%material(ie1)
1264 im2 = Element%material(ie2)
1265 cm = (Material%c(im1)*Spring%hline(1,is) &
1266 + Material%c(im2)*Spring%hline(2,is))/h
1267 phi = (Material%phi(im1)*Spring%hline(1,is) &
1268 + Material%phi(im2)*Spring%hline(2,is))/h
1269 END SUBROUTINE strength
1265,1266行における
変数(cm) がせん断強 $c$ に対する2要素の平均値,1267行,1268行に示す
変数(phi) が内部摩擦角 $\phi$ に対する平均値である.強度定数の場合,必ずしもこのような平均値をとる方法が良いとはいえない場合もあるので,目的に応じて修正すればよい.
変位型のFEMでは,節点変位から要素内ひずみを求めた後,このひずみと構成行列から要素内の応力を計算している.一方,HPMにおいても領域内においてテンソル量としての応力を取り扱う.ただし,HPMでは,全体係数行列で示される連立方程式を解くことで,剛体変位とともに,領域内のひずみを直接求める.したがって,領域内の応力は,このひずみから求めることができる.
具体的なプログラムを
プログラム6.6 に示す.1102行が,解の配列からひずみの解を取り出している箇所である.1104行で領域内の構成行列を作成し,1108行でこの構成行列とひずみの積から領域内の応力を計算している.
プログラム6.6 領域内の応力計算(ElementStress)
1090 !--------------------------------------------------------------------------
1091 SUBROUTINE ElementStress( Element, Material )
1092
1093 TYPE(typeElement), INTENT(IN) :: Element
1094 TYPE(typeMaterial), INTENT(IN) :: Material
1095 REAL(8) :: D(3,3),eps(3),sig(3),ww
1096 INTEGER :: ie,i,j,ii
1097
1098 DO ie = 1, Element%no
1099 IF(Element%node(3,ie) /= 0) THEN
1100 DO i = 1, 3
1101 ii = 3 + i + (ie-1)*Element%dof
1102 eps(i) = Element%ddisp(ii)
1103 END DO
1104 CALL formDmatrix(ie,Element,Material,D)
1105 DO i = 1, 3
1106 ww = 0.D0
1107 DO j = 1, 3
1108 ww = ww + D(i,j)*eps(j)
1109 END DO
1110 sig(i) = ww
1111 END DO
1112 DO i = 1, 3
1113 Element%dstrain(i,ie) = eps(i)
1114 Element%dstress(i,ie) = sig(i)
1115 END DO
1116 END IF
1117 END DO
1118 END SUBROUTINE ElementStress
本サンプルプログラムでは,線形の変位場を用いているため,領域内のひずみは一定となり,したがって,応力も領域内において一定となっている.また,領域内降伏についても,
3.3節 で述べたように,FEMと同様な取り扱いで考慮することができる.ただし,本サンプルプログラムでは,領域内は弾性状態のみを仮定しており,材料非線形と取り扱いの詳細は省略する.
HPMの拘束条件の処理方法には,自由度を直接拘束する方法と,ペナルティ関数を用いて間接的に拘束条件と取り込む方法がある.本サンプルプログラムでは,より一般的な処理が可能な後者の方法で拘束条件を導入している.本節では,のような方法で拘束した場合の反力の計算方法について説明する.
ペナルティ関数を用いた拘束の方法については,
2.5節 に詳細が述べられていが,概略を述べると,拘束辺(点)上の変位が拘束変位(強制変位)量と等しくなるという付帯条件をLagrangeの未定乗数によりハイブリッド型仮想仕事に導入することで拘束条件を考慮する.このとき,Lagrangeの未定乗数 $\boldsymbol{\lambda}$ が物理的には表面力に相当することから,
\[
{\rm (6.3)}
\left. \boldsymbol{\lambda} \right|_{\Gamma_u}
=
\boldsymbol{k} \cdot \left. \boldsymbol{\delta} \right|_{\Gamma_u}
\]
と仮定する.ここで,$\boldsymbol{k}$ はペナルティ関数で,$\left. \boldsymbol{\delta} \right|_{\Gamma_u}$ は,強制変位量 $\hat{\boldsymbol{u}}$ と領域内の変位場から求まる拘束辺(点)上の変位 $\left. \boldsymbol{u}^{(e)} \right|_{\Gamma_u}$ との差で以下のように表される.
\[
{\rm (6.4)}
\left. \boldsymbol{\delta} \right|_{\Gamma_u}
=
\hat{\boldsymbol{u}} - \left. \boldsymbol{u}^{(e)} \right|_{\Gamma_u}
\]
ここで,反力は拘束点と小領域内の拘束点に該当する位置との間の表面力で表されるので,
式(6.3) の $\left. \boldsymbol{\lambda} \right|_{\Gamma_u}$ が反力となる.
以上の関係を基に作成したプログラムを
プログラム6.7 に示す.1290行で入力した強制変位量 $\hat{\boldsymbol{u}}$ をセットし,1305行で拘束位置での変位量 $\left. \boldsymbol{u}^{(e)} \right|_{\Gamma_u}$ を計算している.さらに1307行で,
式(6.3) に基づき反力を計算している.本サンプルプログラムでは,拘束位置として領域境界辺のみを対象としているため,反力の計算にあたり,境界辺に関する数値積分(3点積分)を行い,合力としの反力を求めている.
プログラム6.7 反力計算(Reaction)
1270 !--------------------------------------------------------------------------
1271 SUBROUTINE Reaction( Node, Element, Material, Load, Boundary, Line )
1272
1273 TYPE(typeNode), INTENT(IN) :: Node
1274 TYPE(typeElement), INTENT(IN) :: Element
1275 TYPE(typeMaterial), INTENT(IN) :: Material
1276 TYPE(typeLoad), INTENT(IN) :: Load
1277 TYPE(typeBoundary), INTENT(INOUT) :: Boundary
1278 TYPE(typeNumInteg), INTENT(IN) :: Line
1279
1280 INTEGER :: ib,ie,id,in1,in2,im,in,ip,i
1281 REAL(8) :: f_disp,t,length,shape(2,6),disp(6),uu,reac,wt,pt
1282
1283 pt = Spring%penalty*MAXVAL( Material%young )
1284
1285 DO ib = 1, Boundary%no
1286 ie = Boundary%element(ib)
1287 id = Boundary%direction(ib)
1288 in1 = Boundary%node(1,ib)
1289 in2 = Boundary%node(2,ib)
1290 f_disp = Boundary%disp(ib)
1291 DO i = 1, Element%dof
1292 in = i + (ie-1)*Element%dof
1293 disp(i) = Element%ddisp(in)
1294 END DO
1295 im = Element%material(ie)
1296 t = Material%thick(im)
1297 length = SQRT((Node%coord(1,in2)-Node%coord(1,in1))**2 &
1298 +(Node%coord(2,in2)-Node%coord(2,in1))**2)
1299 reac = 0.D0
1300 DO ip = 1, 3
1301 CALL formShape(ie,ip,in1,in2,Node,Element,Line,shape)
1302 wt = 0.5*Line%weight(ip)*length*t
1303 uu = 0.D0
1304 DO i = 1, Element%dof
1305 uu = uu + shape(id,i)*disp(i)
1306 END DO
1307 reac = reac + (uu - f_disp)*pt*wt
1308 END DO
1309 Boundary%dreaction(ib) = reac
1310 END DO
1311 END SUBROUTINE Reaction
荷重増分法における山田の方法により増分計算を行う場合,荷重増分率はプログラム内部で自動的に計算される.本節では,このことについて若干の補足をする.
塑性流れ則に従えば,すでに降伏しているペナルティ辺の表面力は,除荷が発生しない限り
図6.4(a) に示すよう,降伏面上を移動する.したがって,どのような荷重増分量であれ,降伏条件を破ることはない.ところが,(b)に示すような弾性状態の場合,荷重増分率によっては降伏曲面を越えることもありうる.山田の方法は
3.4節 で示したように,弾性状態の表面力がちょうど降伏面上に載るような荷重増分率を計算している.
$\hspace{1em}$(a) 降伏曲面上の表面力
$\hspace{7em}$(b) 弾性状態
$\hspace{10em}$図6.4 表面力の移動
このような,荷重増分率を計算する流れを示したものが
図6.5 である.すでに降伏しているペナルティ辺については荷重増分率を計算する必要がないため無視し,弾性状態及び除荷状態のペナルティ辺についてのみ荷重増分率の計算を行っている.また,強度定数については,
6.2節 における $\mu$ に関する計算の場合と同様,垂線を重みとして2要素の平均値を用いる.
$\hspace{8em}$図6.5 荷重増分率の計算フロー
3.4節 で説明したように,荷重増分率を計算するためには2次方程式を解かなければならない.そこで,各々の破壊条件に対する2次方程式の係数 $A, B, C$ を求め,各ペナルティ辺に関する荷重増分率を計算する.これをすべてのペナルティ辺について計算し,最小の値を今回の
荷重増分率(minStep) とする.今回までにどれだけの荷重が作用したかは,各荷重増分率の累計を以下のようにとればよい.
\[
{\rm (6.5)}
r_{\rm min} = r_{\rm min} + {\rm minStep}
\]
荷重増分率の累計 $r_{\rm min}$ が1になったとき,想定していた荷重の100%が作用したことになる.
これらの関係をプログラム化したものが
プログラム6.8 に示す
サブルーチン(incRatio) である.1328行~1332行がMohr-Coulombの条件に対する2次方程式の係数を求めている箇所で,l334行~l338行がvonMisesの条件に対するものである.
プログラム6.8 荷重増分率の計算(incRatio)
1312 !--------------------------------------------------------------------------
1313 SUBROUTINE incRatio( Element, Material, Spring, Nonlinear )
1314
1315 TYPE(typeElement), INTENT(IN) :: Element
1316 TYPE(typeMaterial), INTENT(IN) :: Material
1317 TYPE(typeSpring), INTENT(IN) :: Spring
1318 TYPE(typeNonLinear),INTENT(INOUT) :: NonLinear
1319 INTEGER :: is
1320 REAL(8) :: minStep,step,cm,phi,pt,a,b,c
1321 REAL(8) :: PAI = 3.141592654D0
1322
1323 minStep = 9999.D0
1324
1325 DO is = 1, Spring%no
1326 CALL strength(is,Element,Material,Spring,cm,phi)
1327 IF(Element%type == 0) THEN
1328 pt = DTAN(phi*PAI/180.D0)
1329 a = Spring%dstress(2,is)**2 - (Spring%dstress(1,is)*pt)**2
1330 b = 2.D0*(Spring%stress(2,is)*Spring%dstress(2,is) &
1331 + (cm-Spring%stress(1,is)*pt)*Spring%dstress(1,is)*pt)
1332 c = Spring%stress(2,is)**2 - (cm-Spring%stress(1,is)*pt)**2
1333 ELSE
1334 a = (Spring%dstress(1,is)**2)/4.D0 + Spring%dstress(2,is)**2
1335 b = Spring%stress(1,is)*Spring%dstress(1,is)/2.D0 &
1336 + 2.D0*Spring%stress(2,is)*Spring%dstress(2,is)
1337 c = (Spring%stress(1,is)**2)/4.D0 + Spring%stress(2,is)**2 &
1338 - cm**2
1339 END IF
1340 step = ratio(a,b,c)
1341 IF(minStep > step) THEN
1342 minStep = step
1343 END IF
1344 END DO
1345 NonLinear%step = minStep
1346 NonLinear%rmin = NonLinear%rmin + minStep
1347 IF(NonLinear%rmin > 0.9998D0) THEN
1348 NonLinear%step = NonLinear%step - NonLinear%rmin + 1.D0
1349 NonLinear%rmin = 1.D0
1350 END IF
1351 END SUBROUTINE incRatio
2次方程式の根は
プログラム6.9 に示す
関数(ratio) で計算している.このようにして得られた荷重増分率は
変数(step) に割り当てられ,すべてのペナルティ辺に関する
最小荷重増分率(minStep) を1341行~1343行において設定している.この
荷重増分率(minStep) が今回の収束計算における荷重増分率となる.荷重増分率の
累計(NonLinear%rmin) は1345行~1350行において計算している.
数値計算では丸め誤差など,各種の誤差が混入するため,厳密に荷重増分率の累計が1.0となることはまれである.そこで1347行に示すよう,倍精度計算の場合,
NonLinear%rmin が0.9998以上であればほぼ100%の荷重が作用したものとみなし,1349行のように強制的に
NonLinear%rmin を1にセットする.このとき,最後の
荷重増分率(NonLinear%step) には多少の誤差を認め,1348行に示すよう残りの荷重量すベてが載荷するよう再セットする.
なお,1340行における
関数(ratio) は,2次方程式の根を求める関数で,詳細は付録の1353行~1390行に掲載している.
以上のようにして荷重増分率が決定されたなら,今回までの全変位 $\boldsymbol{u}^{n+1}$,全ひずみ $\boldsymbol{\varepsilon}^{n+1}$,および全応力 $\boldsymbol{\sigma}^{n+1}$,全表面力 $\boldsymbol{\lambda}^{n+1}$,全反力 $\boldsymbol{R}^{n+1}$ が以下のように求められる.
\[
{\rm (6.6)}
\left.
\begin{array}{l}
\boldsymbol{u}^{n+1} =
\boldsymbol{u}^{n} + \Delta \boldsymbol{u}^{n+1} \cdot {\rm step} \\[0.3em]
\boldsymbol{\varepsilon}^{n+1} =
\boldsymbol{\varepsilon}^{n} + \Delta \boldsymbol{\varepsilon}^{n+1} \cdot {\rm step} \\[0.3em]
\boldsymbol{\sigma}^{n+1} =
\boldsymbol{\sigma}^{n} + \Delta \boldsymbol{\sigma}^{n+1} \cdot {\rm step} \\[0.3em]
\boldsymbol{\lambda}^{n+1} =
\boldsymbol{\lambda}^{n} + \Delta \boldsymbol{\lambda}^{n+1} \cdot {\rm step} \\[0.3em]
\boldsymbol{R}^{n+1} =
\boldsymbol{R}^{n} + \Delta \boldsymbol{R}^{n+1} \cdot {\rm step}
\end{array}
\right\}
\]
ここで上付きの(n)が前回までの全変位及び全表面力で(n+1)が今回の量であることを示す.
この関係をもとにプログラム化したものが
プログラム6.9 に示す
サブルーチン(totalValue) である.降伏していないペナルティ辺のうち,最も少ない荷重増分量により降伏するであろうと考えられるペナルティ辺より荷重増分率を決定しているため,上式のように得られた全てのペナルティ辺が所有している表面力は降伏曲面上にあるかもしくは弾性状態となり,決して降伏曲面を突き抜けることはない.
プログラム6.9 全変位・全表面力の計算(totalValue)
1391 !--------------------------------------------------------------------------
1392 SUBROUTINE totalValue( Element, Spring, Nonlinear )
1393
1394 TYPE(typeElement), INTENT(INOUT) :: Element
1395 TYPE(typeSpring), INTENT(INOUT) :: Spring
1396 TYPE(typeNonLinear),INTENT(IN) :: NonLinear
1397
1398 Element%disp = Element%disp + Element%ddisp*NonLinear%step
1399 Element%strain = Element%strain + Element%dstrain*NonLinear%step
1400 Element%stress = Element%stress + Element%dstress*NonLinear%step
1401 Spring%strain = Spring%strain + Spring%dstrain*NonLinear%step
1402 Spring%stress = Spring%stress + Spring%dstress*NonLinear%step
1403 Boundary%reaction = Boundary%reaction + Boundary%dreaction*NonLinear%step
1404 END SUBROUTINE totalValue
本サンプル・プログラムでは,隣接する領域境界に設けられたペナルティ辺の降伏のみ考慮しており,引っ張りに伴うペナルティ辺の切断や,領域内の降伏は無視している.もし,これらの破壊要因を考慮するのであれば,それぞれの破壊要因について,本節で説明した荷重増分率を計算し,それらの中の最小値を荷重増分率とするように設定すればよい.
山田の方法を用いた荷重増分計算では増分計算毎に塑性化したペナルティ係数行列や領域内剛性行列を作成し直す.このためには,前回のペナルティ辺や領域内の状態が弾性状態か塑性状態か,あるいは除荷状態か負荷状態かを把握しておく必要がある.本サンプルプログラムでは,ペナルティ辺に関する状態のみ考慮しており,
図6.6 は,その場合の判定の流れを示したものである.
$\hspace{9em}$図6.6 降伏判定のフロー
ここで,この流れに現れる降伏フラッグの種類を整理しておこう
Spring%flag = 0 : 弾性状態
Spring%flag = 1 : 降伏状態
Spring%flag = -2 : 除荷状態
図に示す(*1)の判定は,すでに降伏状態にあるペナルティ辺か否かを判定している.降伏状態にあれば除荷が発生しない限り塑性状態を継続するものとしてフラッグの変更を行わない.もし,ペナルティ辺が降伏状態でなければ除荷状態か否かを判定し,除荷状態であれば以後弾性と見なし,フラッグを
Spring%flag = -2 にセットする.(*2)の判定文は今回の表面力が降伏しているか否かの判定で,もし,降伏していればフラッグを1とし,以後,塑性としての取り扱いをする.このフローをプログラム化したものが
プログラム6.10 に示すサブルーチン(YieldCheck)である.
プログラム6.10 降伏判定(YieldCheck)
1405 !-------------------------------------------------------------------------
1406 SUBROUTINE YieldCheck( Element, Material, Spring )
1407
1408 TYPE(typeElement), INTENT(IN) :: Element
1409 TYPE(typeMaterial), INTENT(IN) :: Material
1410 TYPE(typeSpring), INTENT(IN) :: Spring
1411 INTEGER :: is
1412 REAL(8) :: cm,phi,pt,tau
1413 REAL(8) :: PAI = 3.141592654D0
1414
1415 DO is = 1, Spring%no
1416 IF(Spring%flag(is) /= 1) THEN
1417 IF(Spring%flag(is) ==2) THEN
1418 Spring%flag(is) = -2
1419 ELSE
1420 CALL strength(is,Element,Material,Spring,cm,phi)
1421 IF(Element%type == 0) THEN
1422 cm = cm*0.998D0
1423 pt = DTAN(phi*PAI/180.0)
1424 tau = ABS(Spring%stress(2,is))+Spring%stress(1,is)*pt
1425 IF(tau > cm) THEN
1426 Spring%flag(is) = 1
1427 END IF
1428 ELSE
1429 cm = cm**2*0.998D0
1430 tau = Spring%stress(1,is)**2/4.D0 + Spring%stress(2,is)**2
1431 IF(tau > cm) THEN
1432 Spring%flag(is) = 1
1433 END IF
1434 END IF
1435 END IF
1436 END IF
1437 END DO
1438 END SUBROUTINE YieldCheck
この判定で注意してほしいことはl422行と1429行においてせん断強さに0.998を掛けていることである.厳密にはこのような処理を行う必要はないが,実数計算の場合,丸め誤差等により本来1となるべき解が0.99…となってしまうことが度々ある.前節で説明した全表面力の計算も実数計算であるから,表面力が降伏曲面上に完全に一致することは少ない.
$\hspace{2em}$図6.7 誤差の許容範囲
そこで,
図6.7 に示すよう,ある程度許容範囲を設け,現在の表面力がそれ以上なら降伏とみなす方法をとる.山田の方法では一つ一つペナルティ辺を降伏させてゆくが,このような許容範囲を与えることで,降伏強度に非常に近い表面力を持つペナルティ辺が存在した場合,一度に何箇所か降伏することもありうる.しかし,あまり厳密に判定したとしても精度はそれほど上がらないことも多く,場合によっては解の収束性を損なうこともある.筆者らの経験では単精度の場合で0.98程度,倍精度の場合で0.998程度の設定によりあまり誤差の無い極限荷重を得ている.