├── README.md ├── mechanical.py └── vol.py /README.md: -------------------------------------------------------------------------------- 1 | # RVE-homogenization-of-TPMS-structures 2 | A voxel based python script for elastic homogenization of four triply peridic minimal surface-based structures in Abaqus. 3 | Schwartz, IWP, Diamond and Gyroid structures can be analyzed. 4 | 5 | -------------------------------------------------------------------------------- /mechanical.py: -------------------------------------------------------------------------------- 1 | # Homogenization thermal properties of the voxelized RVE 2 | # This Code is Written By Fayyaz Nosouhi (dehnavifn@gmail.com) 3 | # Tehran University March-2020 4 | 5 | from abaqus import * 6 | from abaqusConstants import * 7 | import __main__ 8 | import section 9 | import regionToolset 10 | import displayGroupMdbToolset as dgm 11 | import part 12 | import material 13 | import assembly 14 | import step 15 | import interaction 16 | import load 17 | import mesh 18 | import optimization 19 | import job 20 | import sketch 21 | import visualization 22 | import xyPlot 23 | import displayGroupOdbToolset as dgo 24 | import numpy as np 25 | import time 26 | from operator import itemgetter 27 | time_strat=time.asctime( time.localtime(time.time()) ) 28 | 29 | #Parameters--------------------------------------------------------------------- 30 | Nx=60 31 | Ny=60 32 | Nz=60 33 | ax=1 # factor of the cell lenhth in x direction 34 | ay=1 35 | az=1 36 | E0=.0000001 #thermal cond. of phase 0 (void) 37 | v0=.1 38 | E1=72000 # ther. cond. of phase 1 (solid) 39 | v1=.33 40 | 41 | CPU_No=2 42 | ModelName="Schwarz0_1" 43 | RVE_Type='Schwarz' # RVE_Type: IWP, Schwarz, Gyroid, Diamond 44 | Vol=30 45 | cx=cy=cz=1 # cell number 46 | jobName=ModelName 47 | #--------------------------------------------------------- 48 | execfile('vol.py') 49 | xyz=Nx*Ny*Nz 50 | Lx=2*cx*pi 51 | Ly=2*cy*pi 52 | Lz=2*cz*pi 53 | 54 | C=np.zeros([xyz]) 55 | c1=(Lx)/Nx 56 | c2=(Ly)/Ny 57 | c3=(Lz)/Nz 58 | if (RVE_Type== 'IWP'): 59 | vol_t=iwp_vol 60 | elif (RVE_Type== 'Schwarz'): 61 | vol_t=sch_vol 62 | elif (RVE_Type== 'Gyroid'): 63 | vol_t=gyr_vol 64 | else : 65 | vol_t=dim_vol 66 | 67 | 68 | 69 | 70 | t=0 71 | Q=0 72 | # 73 | for q in range (len(vol_t)/2): 74 | if vol_t[q*2+1]>Vol: 75 | t=vol_t[2*q-2] 76 | Q=q-1 77 | break 78 | 79 | 80 | 81 | # 82 | while (True): 83 | C=np.zeros([xyz]) 84 | for i in range (Nx): 85 | for j in range (Ny): 86 | for k in range (Nz): 87 | if (RVE_Type== 'IWP' or RVE_Type== 'Schwarz' or RVE_Type== 'Diamond'): 88 | x=(((i-Nx/2.)*c1)-.0*pi) 89 | y=(((j-Ny/2.)*c2)-.0*pi) 90 | z=(((k-Nz/2.)*c3)-.0*pi) 91 | elif (RVE_Type== 'Gyroid'): 92 | x=(((i-Nx/2.)*c1)-.28*pi) 93 | y=(((j-Ny/2.)*c2)-.28*pi) 94 | z=(((k-Nz/2.)*c3)-.28*pi) 95 | else: 96 | print("RVE_Type is not valid! select IWP, Schwarz, Gyroid or Diamond") 97 | break 98 | # 99 | if (RVE_Type== 'Diamond'): 100 | a=sin(x)*sin(y)*sin(z)+sin(x)*cos(y)*cos(z)+cos(x)*sin(y)*cos(z)+cos(x)*cos(y)*sin(z) #DIAMOND 101 | elif(RVE_Type== 'Gyroid'): 102 | a=cos(x)*sin(y)+cos(y)*sin(z)+cos(z)*sin(x) # Gyroide <1.2 & yzx-0.28*pi 103 | elif (RVE_Type== 'Schwarz'): 104 | a=cos(x)+cos(y)+cos(z) #schwartz 105 | else : 106 | a=(cos(2*x)+cos(2*y)+cos(2*z)-2*(cos(x)*cos(y)+cos(y)*cos(z)+cos(z)*cos(x))) #IWP 107 | #------------------------------------------------------------------------------------- 108 | if aVol): 112 | if (RVE_Type== 'Schwarz'): 113 | C=np.fft.ifftshift((C.reshape(Nx, Ny, Nz))) 114 | C=C.reshape(Nx*Ny*Nz) 115 | break 116 | else: 117 | t=t+0.001 118 | print(VF, t) 119 | 120 | #Generating a RVE size Nx*Ny*Nz(pixel size 1)----------------------------------- 121 | Nx=Nx*ax 122 | Ny=Ny*ay 123 | Nz=Nz*az 124 | mdb.Model(name=ModelName, modelType=STANDARD_EXPLICIT) 125 | #os.chdir(os.getcwd()+dirName) 126 | s = mdb.models[ModelName].ConstrainedSketch(name='__profile__', 127 | sheetSize=200.0) 128 | g, v, d, c = s.geometry, s.vertices, s.dimensions, s.constraints 129 | s.setPrimaryObject(option=STANDALONE) 130 | s.rectangle(point1=(0.0, 0.0), point2=(Nx, Ny)) 131 | p = mdb.models[ModelName].Part(name='Part-1', dimensionality=THREE_D, 132 | type=DEFORMABLE_BODY) 133 | p = mdb.models[ModelName].parts['Part-1'] 134 | p.BaseSolidExtrude(sketch=s, depth=Nz) 135 | s.unsetPrimaryObject() 136 | p = mdb.models[ModelName].parts['Part-1'] 137 | session.viewports['Viewport: 1'].setValues(displayedObject=p) 138 | del mdb.models[ModelName].sketches['__profile__'] 139 | #Material--------------------------------------------------------------------- 140 | mdb.models[ModelName].Material(name='Material-0') 141 | mdb.models[ModelName].materials['Material-0'].Elastic(table=((E0, v0), )) 142 | mdb.models[ModelName].Material(name='Material-1') 143 | mdb.models[ModelName].materials['Material-1'].Elastic(table=((E1, v1), )) 144 | 145 | mdb.models[ModelName].HomogeneousSolidSection(name='Section-0', material='Material-0', thickness=None) 146 | mdb.models[ModelName].HomogeneousSolidSection(name='Section-1', material='Material-1', thickness=None) 147 | #Assembly-------------------------------------------------------------------- 148 | a = mdb.models[ModelName].rootAssembly 149 | session.viewports['Viewport: 1'].setValues(displayedObject=a) 150 | session.viewports['Viewport: 1'].assemblyDisplay.setValues( 151 | optimizationTasks=OFF, geometricRestrictions=OFF, stopConditions=OFF) 152 | a = mdb.models[ModelName].rootAssembly 153 | a.DatumCsysByDefault(CARTESIAN) 154 | p = mdb.models[ModelName].parts['Part-1'] 155 | a.Instance(name='Part-1-1', part=p, dependent=ON) 156 | #Steps----------------------------------------------------------------------- 157 | mdb.models[ModelName].StaticStep(name='Step-1', previous='Initial') 158 | mdb.models[ModelName].steps['Step-1'].setValues(matrixSolver=ITERATIVE, matrixStorage=SYMMETRIC) 159 | mdb.models[ModelName].StaticStep(name='Step-2', previous='Step-1') 160 | mdb.models[ModelName].steps['Step-2'].setValues(matrixSolver=ITERATIVE, matrixStorage=SYMMETRIC) 161 | mdb.models[ModelName].StaticStep(name='Step-3', previous='Step-2') 162 | mdb.models[ModelName].steps['Step-3'].setValues(matrixSolver=ITERATIVE, matrixStorage=SYMMETRIC) 163 | mdb.models[ModelName].StaticStep(name='Step-4', previous='Step-3') 164 | mdb.models[ModelName].steps['Step-4'].setValues(matrixSolver=ITERATIVE, matrixStorage=SYMMETRIC) 165 | mdb.models[ModelName].StaticStep(name='Step-5', previous='Step-4') 166 | mdb.models[ModelName].steps['Step-5'].setValues(matrixSolver=ITERATIVE, matrixStorage=SYMMETRIC) 167 | mdb.models[ModelName].StaticStep(name='Step-6', previous='Step-5') 168 | mdb.models[ModelName].steps['Step-6'].setValues(matrixSolver=ITERATIVE, matrixStorage=SYMMETRIC) 169 | 170 | mdb.models[ModelName].fieldOutputRequests['F-Output-1'].setValues(variables=('S', 'LE')) 171 | 172 | #boundary condition------------------------------------------------------- 173 | a = mdb.models[ModelName].rootAssembly 174 | f1 = a.instances['Part-1-1'].faces 175 | 176 | #1- tension direction x---------- 177 | faces1 = f1.findAt(((Nx, .001*Ny, 0.001*Nz),)) 178 | region = a.Set(faces=faces1, name='Set-2') 179 | mdb.models[ModelName].DisplacementBC(name='BC-1', createStepName='Step-1', 180 | region=region, u1=0.1, u2=0.0, u3=0.0, ur1=0.0, ur2=0.0, ur3=0.0, 181 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 182 | localCsys=None) 183 | # 184 | faces1 = f1.findAt(((0, .001*Ny, 0.001*Nz),)) 185 | region = a.Set(faces=faces1, name='Set-3') 186 | mdb.models[ModelName].DisplacementBC(name='BC-2', createStepName='Step-1', 187 | region=region, u1=0.0, u2=0.0, u3=0.0, ur1=0.0, ur2=0.0, ur3=0.0, 188 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 189 | localCsys=None) 190 | 191 | mdb.models[ModelName].boundaryConditions['BC-1'].deactivate('Step-2') 192 | mdb.models[ModelName].boundaryConditions['BC-2'].deactivate('Step-2') 193 | 194 | # tension direction y----------- 195 | faces1 = f1.findAt(((.001*Nx, Ny, 0.001*Nz),)) 196 | region = a.Set(faces=faces1, name='Set-4') 197 | mdb.models[ModelName].DisplacementBC(name='BC-3', createStepName='Step-2', 198 | region=region, u1=0.0, u2=0.1, u3=0.0, ur1=0.0, ur2=0.0, ur3=0.0, 199 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 200 | localCsys=None) 201 | 202 | faces1 = f1.findAt(((.001*Nx, 0, 0.001*Nz),)) 203 | region = a.Set(faces=faces1, name='Set-5') 204 | mdb.models[ModelName].DisplacementBC(name='BC-4', createStepName='Step-2', 205 | region=region, u1=0.0, u2=0.0, u3=0.0, ur1=0.0, ur2=0.0, ur3=0.0, 206 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 207 | localCsys=None) 208 | 209 | mdb.models[ModelName].boundaryConditions['BC-3'].deactivate('Step-3') 210 | mdb.models[ModelName].boundaryConditions['BC-4'].deactivate('Step-3') 211 | 212 | # tension direction z----------- 213 | faces1 = f1.findAt(((.001*Nx, 0.001*Ny, Nz),)) 214 | region = a.Set(faces=faces1, name='Set-6') 215 | mdb.models[ModelName].DisplacementBC(name='BC-5', createStepName='Step-3', 216 | region=region, u1=0.0, u2=0.0, u3=0.1, ur1=0.0, ur2=0.0, ur3=0.0, 217 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 218 | localCsys=None) 219 | 220 | 221 | faces1 = f1.findAt(((.001*Nx, 0.001*Ny, 0),)) 222 | region = a.Set(faces=faces1, name='Set-7') 223 | mdb.models[ModelName].DisplacementBC(name='BC-6', createStepName='Step-3', 224 | region=region, u1=0.0, u2=0, u3=0.0, ur1=0.0, ur2=0.0, ur3=0.0, 225 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 226 | localCsys=None) 227 | 228 | mdb.models[ModelName].boundaryConditions['BC-5'].deactivate('Step-4') 229 | mdb.models[ModelName].boundaryConditions['BC-6'].deactivate('Step-4') 230 | 231 | # shear direction xy---------- 232 | 233 | faces1 = f1.findAt(((Nx, 0.001*Ny, .001*Nz),)) 234 | region = a.Set(faces=faces1, name='Set-8') 235 | mdb.models[ModelName].DisplacementBC(name='BC-7', createStepName='Step-4', 236 | region=region, u1=0.0, u2=0.05, u3=0.0, ur1=0.0, ur2=0.0, ur3=0.0, 237 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 238 | localCsys=None) 239 | 240 | faces1 = f1.findAt(((0, 0.001*Ny, .001*Nz),)) 241 | region = a.Set(faces=faces1, name='Set-9') 242 | mdb.models[ModelName].DisplacementBC(name='BC-8', createStepName='Step-4', 243 | region=region, u1=0.0, u2=-0.05, u3=0, ur1=0.0, ur2=0.0, ur3=0.0, 244 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 245 | localCsys=None) 246 | 247 | mdb.models[ModelName].boundaryConditions['BC-7'].deactivate('Step-5') 248 | mdb.models[ModelName].boundaryConditions['BC-8'].deactivate('Step-5') 249 | 250 | # shear direction xz---------- 251 | faces1 =f1.findAt(((0.001*Nx, 0.001*Ny, Nz),)) 252 | region = a.Set(faces=faces1, name='Set-10') 253 | mdb.models[ModelName].DisplacementBC(name='BC-9', createStepName='Step-5', 254 | region=region, u1=0.05, u2=0, u3=0, ur1=0.0, ur2=0.0, ur3=0.0, 255 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 256 | localCsys=None) 257 | 258 | faces1 = f1.findAt(((0.001*Nx, 0.001*Ny, 0),)) 259 | region = a.Set(faces=faces1, name='Set-11') 260 | mdb.models[ModelName].DisplacementBC(name='BC-10', createStepName='Step-5', 261 | region=region, u1=-0.05, u2=0, u3=0.0, ur1=0.0, ur2=0.0, ur3=0.0, 262 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 263 | localCsys=None) 264 | 265 | mdb.models[ModelName].boundaryConditions['BC-9'].deactivate('Step-6') 266 | mdb.models[ModelName].boundaryConditions['BC-10'].deactivate('Step-6') 267 | # shear direction xz---------- 268 | faces1 =f1.findAt(((0.001*Nx, Ny, .001*Nz),)) 269 | region = a.Set(faces=faces1, name='Set-12') 270 | mdb.models[ModelName].DisplacementBC(name='BC-11', createStepName='Step-6', 271 | region=region, u1=0.0, u2=0.0, u3=0.05, ur1=0.0, ur2=0.0, ur3=0.0, 272 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 273 | localCsys=None) 274 | 275 | faces1 = f1.findAt(((0.001*Nx, 0, .001*Nz),)) 276 | region = a.Set(faces=faces1, name='Set-13') 277 | mdb.models[ModelName].DisplacementBC(name='BC-12', createStepName='Step-6', 278 | region=region, u1=0, u2=0.0, u3=-0.05, ur1=0.0, ur2=0.0, ur3=0.0, 279 | amplitude=UNSET, fixed=OFF, distributionType=UNIFORM, fieldName='', 280 | localCsys=None) 281 | #-------------------------------------------------------------------------------- 282 | #Meshing------------------------------------------------------------------------- 283 | elemType1 = mesh.ElemType(elemCode=C3D8R, elemLibrary=STANDARD) 284 | p = mdb.models[ModelName].parts['Part-1'] 285 | e = p.edges 286 | # 287 | e1 = e.findAt(((Nx, 0, .001*Nz),),) 288 | e2 = e.findAt(((0, Ny, .001*Nz),),) 289 | e3 = e.findAt(((0, 0, .001*Nz),),) 290 | e4 = e.findAt(((Nx, Ny, .001*Nz),),) 291 | 292 | e5 = e.findAt(((Nx, .001*Ny, 0),),) 293 | e6 = e.findAt(((0, .001*Ny, Nz),),) 294 | e7 = e.findAt(((Nx, .001*Ny, Nz),),) 295 | e8 = e.findAt(((0, .001*Ny, 0),),) 296 | 297 | e5 = e.findAt(((.001*Nx, 0, .0),),) 298 | e6 = e.findAt(((.001*Nx, Ny, 0),),) 299 | # 300 | p.seedEdgeByNumber(edges=(e5+e6), number=Nx/ax, constraint=FINER) 301 | p.seedEdgeByNumber(edges=(e3+e4), number=Ny/ay, constraint=FINER) 302 | p.seedEdgeByNumber(edges=(e1+e2), number=Nz/az, constraint=FINER) 303 | # 304 | p.generateMesh() 305 | c = p.cells 306 | #cells = c.getSequenceFromMask(mask=('[#1 ]', ), ) 307 | cells = c.findAt(((.001*Nx, .001*Ny, .001*Nz),),) 308 | p.setElementType(regions=(cells, ), elemTypes=(elemType1, )) 309 | #--------------------------------------------- 310 | #Creat two set for two diffrent materials (0 and 1) 311 | setMat0=[] 312 | setMat1=[] 313 | el=p.elements 314 | for i in range (len(C)): 315 | if C[i]==0: 316 | setMat0.append(el[i].label) 317 | else: 318 | 319 | setMat1.append(el[i].label) 320 | 321 | 322 | #- 323 | elset0=el.sequenceFromLabels(setMat0) 324 | elset1=el.sequenceFromLabels(setMat1) 325 | region1=p.Set(elements=elset0, name='SetMat0') 326 | region2=p.Set(elements=elset1, name='SetMat1') 327 | p.SectionAssignment(region=region1, sectionName='Section-0', offset=0.0, 328 | offsetType=MIDDLE_SURFACE, offsetField='', thicknessAssignment=FROM_SECTION) 329 | p.SectionAssignment(region=region2, sectionName='Section-1', offset=0.0, 330 | offsetType=MIDDLE_SURFACE, offsetField='', thicknessAssignment=FROM_SECTION) 331 | #Job------------------------------------------------------------------------------- 332 | 333 | mdb.Job(name=jobName, model=ModelName, description='', type=ANALYSIS, 334 | atTime=None, waitMinutes=0, waitHours=0, queue=None, memory=90, 335 | memoryUnits=PERCENTAGE, getMemoryFromAnalysis=True, 336 | explicitPrecision=SINGLE, nodalOutputPrecision=SINGLE, echoPrint=OFF, 337 | modelPrint=OFF, contactPrint=OFF, historyPrint=OFF, userSubroutine='', 338 | scratch='', multiprocessingMode=DEFAULT, numCpus=CPU_No, numDomains=CPU_No, 339 | numGPUs=0) 340 | mdb.jobs[jobName].submit(consistencyChecking=OFF) 341 | mdb.jobs[jobName].waitForCompletion() 342 | #Homogenization------------------------------------------------------------------------ 343 | 344 | modb = session.openOdb(name=jobName+'.odb') 345 | n1=modb.rootAssembly.instances['PART-1-1'] 346 | 347 | epMatrix = np.zeros(shape=(6,6), dtype=float) 348 | sigMatrix= np.zeros(shape=(6,6), dtype=float) 349 | Cmatrix = np.zeros(shape=(6,6), dtype=float) 350 | 351 | steps=['Step-1','Step-2','Step-3','Step-4','Step-5','Step-6'] 352 | 353 | for i in range (6): 354 | S=modb.steps[steps[i]].frames[-1].fieldOutputs['S'].getSubset(region=n1) 355 | E=modb.steps[steps[i]].frames[-1].fieldOutputs['E'].getSubset(region=n1) 356 | for j in range (6): 357 | for k in range (len(S.values)): 358 | epMatrix [j][i]= epMatrix [j][i]+E.values[k].data[j] 359 | sigMatrix[i][j]= sigMatrix[i][j]+S.values[k].data[j] 360 | 361 | 362 | 363 | ep_inv= np.linalg.inv(epMatrix) 364 | for i in range (6): 365 | Cmatrix[:,i]=np.dot(ep_inv, sigMatrix[i,:]) 366 | 367 | 368 | time_fin=time.asctime( time.localtime(time.time()) ) 369 | 370 | fid=open(ModelName+'.txt', 'w') 371 | fid.write("E l a s t i c H o m o g e n i z a t i o n U s i n g A b a q u s\n\n" ) 372 | fid.write("-------------------------------------------------\n" ) 373 | 374 | 375 | vol_phase1=C.sum()/(1.0*Nx*Ny*Nz) 376 | 377 | fid.write("Volume fraction Phase 1 = %5.4f\n" % (vol_phase1) ) 378 | fid.write("E Phase 1 = %5.4f\n" % (E1) ) 379 | fid.write("v Phase 1 = %5.4f\n\n" % (v1) ) 380 | 381 | fid.write("-------------------------------------------------\n" ) 382 | fid.write("Volume fraction Phase 0 = %5.4f\n" % (1-vol_phase1) ) 383 | fid.write("E Phase 0 = %5.4f\n" % (E0) ) 384 | fid.write("v Phase 0 = %5.4f\n\n" % (v0) ) 385 | fid.write("-------------------------------------------------\n" ) 386 | fid.write("C_homogenized=\n" ) 387 | np.savetxt(fid, (Cmatrix[0,:],Cmatrix[1,:],Cmatrix[2,:],Cmatrix[3,:],Cmatrix[4,:],Cmatrix[5,:], ), fmt="%f %f %f %f %f %f") 388 | Smatrix=np.linalg.inv(Cmatrix) 389 | 390 | fid.write(" \n\n" ) 391 | fid.write("-------------------------------------------------\n" ) 392 | fid.write("E11= %5.4f\n" % (1./Smatrix[0,0]) ) 393 | fid.write("E22= %5.4f\n" % (1./Smatrix[1,1]) ) 394 | fid.write("E33= %5.4f\n" % (1./Smatrix[2,2]) ) 395 | 396 | 397 | fid.write("-------------------------------------------------\n" ) 398 | fid.write("Start and finish time\n" ) 399 | fid.write(time_strat) 400 | fid.write("\n") 401 | fid.write(time_fin) 402 | 403 | fid.close() 404 | 405 | dir_name = os.getcwd() 406 | test = os.listdir(dir_name) 407 | for item in test: 408 | if ( item.endswith(".com") or item.endswith(".inp") or item.endswith(".ipm")or \ 409 | item.endswith(".log") or item.endswith(".prt") or item.endswith(".sim")or \ 410 | item.endswith(".sta") or item.endswith(".rpy") or item.endswith(".1") or item.endswith(".rec")or item.endswith(".C")): 411 | os.remove(os.path.join(dir_name, item)) 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | --------------------------------------------------------------------------------