diff --git a/experiment/perforated-bilayer/PolarPlotLocalEnergy.py b/experiment/perforated-bilayer/PolarPlotLocalEnergy.py new file mode 100644 index 0000000000000000000000000000000000000000..4ed2e4aae50f9a3f985db2ed7c174b1af2281e17 --- /dev/null +++ b/experiment/perforated-bilayer/PolarPlotLocalEnergy.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Wed Jul 6 13:17:28 2022 + +@author: stefan +""" +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.colors as colors +import codecs + + + +def energy(kappa,alpha,Q,B) : + G=kappa*np.array([[np.cos(alpha)**2],[np.sin(alpha)**2],[np.sqrt(2)*np.cos(alpha)*np.sin(alpha)]])-B + return np.matmul(np.transpose(G),np.matmul(Q,G))[0,0] + +def xytokappaalpha(x,y): + + if y>0: + return [np.sqrt(x**2+y**2), np.abs(np.arctan2(y,x))] + else: + return [-np.sqrt(x**2+y**2), np.abs(np.arctan2(y,x))] + +# Read effective quantites +def ReadEffectiveQuantities(QFilePath, BFilePath): + # Read Output Matrices (effective quantities) + # From Cell-Problem output Files : ../outputs/Qmatrix.txt , ../outputs/Bmatrix.txt + # -- Read Matrix Qhom + X = [] + # with codecs.open(path + '/outputs/QMatrix.txt', encoding='utf-8-sig') as f: + with codecs.open(QFilePath, encoding='utf-8-sig') as f: + for line in f: + s = line.split() + X.append([float(s[i]) for i in range(len(s))]) + Q = np.array([[X[0][2], X[1][2], X[2][2]], + [X[3][2], X[4][2], X[5][2]], + [X[6][2], X[7][2], X[8][2]] ]) + + # -- Read Beff (as Vector) + X = [] + # with codecs.open(path + '/outputs/BMatrix.txt', encoding='utf-8-sig') as f: + with codecs.open(BFilePath, encoding='utf-8-sig') as f: + for line in f: + s = line.split() + X.append([float(s[i]) for i in range(len(s))]) + B = np.array([X[0][2], X[1][2], X[2][2]]) + return Q, B + +# Number of experiments / folders +number=4 +kappa=np.zeros(number) +for n in range(0,number): + # Read from Date + print(str(n)) + DataPath = './experiment/perforated-bilayer/results/'+str(n) + DataPath = './experiment/perforated-bilayer/results/'+str(n) + QFilePath = DataPath + '/QMatrix.txt' + BFilePath = DataPath + '/BMatrix.txt' + Q, B = ReadEffectiveQuantities(QFilePath,BFilePath) + # Q=0.5*(np.transpose(Q)+Q) # symmetrize + B=np.transpose([B]) + # + + N=300 + length=12 + r, theta = np.meshgrid(np.linspace(0,length,N),np.radians(np.linspace(0, 360, N))) + E=np.zeros(np.shape(r)) + for i in range(0,N): + for j in range(0,N): + if theta[i,j]<np.pi: + E[i,j]=energy(r[i,j],theta[i,j],Q,B) + else: + E[i,j]=energy(-r[i,j],theta[i,j],Q,B) + + # Compute Minimizer + [imin,jmin]=np.unravel_index(E.argmin(),(N,N)) + kappamin=r[imin,jmin] + alphamin=theta[imin,jmin] + kappa[n]=kappamin + fig, ax = plt.subplots(figsize=(6,6),subplot_kw=dict(projection='polar')) + levs=np.geomspace(E.min(),E.max(),400) + pcm=ax.contourf(theta, r, E, levs, norm=colors.PowerNorm(gamma=0.2), cmap='brg') + ax.set_xticks([0,np.pi/2]) + ax.set_yticks([kappamin]) + colorbarticks=np.linspace(E.min(),E.max(),6) + plt.colorbar(pcm, extend='max', ticks=colorbarticks, pad=0.1) + plt.show() + +f = open("./experiment/perforated-bilayer/results/kappa_simulation.txt", "w") +f.write(str(kappa)) +f.close() + + diff --git a/experiment/perforated-bilayer/perfBilayer_test.py b/experiment/perforated-bilayer/perfBilayer_test.py new file mode 100644 index 0000000000000000000000000000000000000000..c580079027edf990fd4fa9ad5801fe2e66a8e80b --- /dev/null +++ b/experiment/perforated-bilayer/perfBilayer_test.py @@ -0,0 +1,193 @@ +import subprocess +import re +import os +import numpy as np +import matplotlib.pyplot as plt +import math +import fileinput +import time +import matplotlib.ticker as tickers +import matplotlib as mpl +from matplotlib.ticker import MultipleLocator,FormatStrFormatter,MaxNLocator +import codecs +import sys +import threading + +# # Schreibe input datei für Parameter +# def SetParametersCellProblem(ParameterSet, ParsetFilePath, outputPath): +# print('----set Parameters -----') +# with open(ParsetFilePath, 'r') as file: +# filedata = file.read() +# filedata = re.sub('(?m)^materialFunction\s?=.*','materialFunction = '+str(ParameterSet.materialFunction),filedata) +# filedata = re.sub('(?m)^gamma\s?=.*','gamma='+str(ParameterSet.gamma),filedata) +# filedata = re.sub('(?m)^numLevels\s?=.*','numLevels='+str(ParameterSet.numLevels)+' '+str(ParameterSet.numLevels) ,filedata) +# filedata = re.sub('(?m)^outputPath\s?=\s?.*','outputPath='+str(outputPath),filedata) +# f = open(ParsetFilePath,'w') +# f.write(filedata) +# f.close() + + +# # Ändere Parameter der MaterialFunction +# def SetParameterMaterialFunction(materialFunction, parameterName, parameterValue): +# with open(Path+"/"+materialFunction+'.py', 'r') as file: +# filedata = file.read() +# filedata = re.sub('(?m)^'+str(parameterName)+'\s?=.*',str(parameterName)+' = '+str(parameterValue),filedata) +# f = open(Path+"/"+materialFunction+'.py','w') +# f.write(filedata) +# f.close() + +def SetParameterMaterialFunction(inputFunction, parameterName, parameterValue): + with open(inputFunction+'.py', 'r') as file: + filedata = file.read() + filedata = re.sub('(?m)^'+str(parameterName)+'\s?=.*',str(parameterName)+' = '+str(parameterValue),filedata) + f = open(inputFunction+'.py','w') + f.write(filedata) + f.close() + + + +# # Rufe Programm zum Lösen des Cell-Problems auf +# def run_CellProblem(executable, parset,write_LOG): +# print('----- RUN Cell-Problem ----') +# processList = [] +# LOGFILE = "Cell-Problem_output.log" +# print('LOGFILE:',LOGFILE) +# print('executable:',executable) +# if write_LOG: +# p = subprocess.Popen(executable + parset +# + " | tee " + LOGFILE, shell=True) + +# else: +# p = subprocess.Popen(executable + parset +# + " | tee " + LOGFILE, shell=True) + +# p.wait() # wait +# processList.append(p) +# exit_codes = [p.wait() for p in processList] + +# return + +# Read effective quantites +def ReadEffectiveQuantities(QFilePath = os.path.dirname(os.getcwd()) + '/outputs/QMatrix.txt', BFilePath = os.path.dirname(os.getcwd())+ '/outputs/BMatrix.txt'): + # Read Output Matrices (effective quantities) + # From Cell-Problem output Files : ../outputs/Qmatrix.txt , ../outputs/Bmatrix.txt + # -- Read Matrix Qhom + X = [] + # with codecs.open(path + '/outputs/QMatrix.txt', encoding='utf-8-sig') as f: + with codecs.open(QFilePath, encoding='utf-8-sig') as f: + for line in f: + s = line.split() + X.append([float(s[i]) for i in range(len(s))]) + Q = np.array([[X[0][2], X[1][2], X[2][2]], + [X[3][2], X[4][2], X[5][2]], + [X[6][2], X[7][2], X[8][2]] ]) + + # -- Read Beff (as Vector) + X = [] + # with codecs.open(path + '/outputs/BMatrix.txt', encoding='utf-8-sig') as f: + with codecs.open(BFilePath, encoding='utf-8-sig') as f: + for line in f: + s = line.split() + X.append([float(s[i]) for i in range(len(s))]) + B = np.array([X[0][2], X[1][2], X[2][2]]) + return Q, B + +# Function for evaluating the energy in terms of kappa, alpha and Q, B +def eval_energy(kappa,alpha,Q,B) : + G=kappa*np.array([[np.cos(alpha)**2],[np.sin(alpha)**2],[np.sqrt(2)*np.cos(alpha)*np.sin(alpha)]])-B + return np.matmul(np.transpose(G),np.matmul(Q,G))[0,0] + +#------------------------------------------------------------------------------------------------------- +######################## +#### SET PARAMETERS #### +######################## +# ----- Setup Paths ----- +# write_LOG = True # writes Cell-Problem output-LOG in "Cell-Problem_output.log" +# path='/home/klaus/Desktop/Dune_release/dune-microstructure/experiment/wood-bilayer/results/' +# pythonPath = '/home/klaus/Desktop/Dune_release/dune-microstructure/experiment/wood-bilayer' +path = os.getcwd() + '/experiment/perforated-bilayer/results/' +pythonPath = os.getcwd() + '/experiment/perforated-bilayer' +# pythonModule = "perforated_wood_upper" +pythonModule = "perforated_wood_lower" +executable = os.getcwd() + '/build-cmake/src/Cell-Problem' +# --------------------------------- +# Setup Experiment +# --------------------------------- +gamma = 1.0 + +# ----- Define Parameters for Material Function -------------------- +# [r, h, omega_flat, omega_target, theta, experimental_kappa] +# r = (thickness upper layer)/(thickness) +# h = thickness [meter] +# omega_flat = moisture content in the flat state before drying [%] +# omega_target = moisture content in the target state [%] +# theta = rotation angle (not implemented and used) +# beta = design parameter for perforation = ratio of Volume of (cylindrical) perforation to Volume of active/passive layer + +#Experiment: Perforate "active" bilayer phase +materialFunctionParameter=[ + [0.22, 0.0053, 17.17547062, 8.959564147, 0.0, 0.0 ], + [0.22, 0.0053, 17.17547062, 8.959564147, 0.0, 0.1 ], + [0.22, 0.0053, 17.17547062, 8.959564147, 0.0, 0.2 ], + [0.22, 0.0053, 17.17547062, 8.959564147, 0.0, 0.3 ] + # [0.22, 0.0053, 17.17547062, 8.959564147, 0.0, 0.4 ], + # [0.22, 0.0053, 17.17547062, 8.959564147, 0.0, 0.5 ] +] + +# ------ Loops through Parameters for Material Function ----------- +for i in range(0,np.shape(materialFunctionParameter)[0]): + print("------------------") + print("New Loop") + print("------------------") + # Check output directory + outputPath = path + str(i) + isExist = os.path.exists(outputPath) + if not isExist: + # Create a new directory because it does not exist + os.makedirs(outputPath) + print("The new directory " + outputPath + " is created!") + + # thread = threading.Thread(target=run_CellProblem(executable, pythonModule, pythonPath, LOGFILE)) + # thread.start() + + #TODO: apperently its not possible to pass a variable via subprocess and "calculate" another input value inside the python file. + # Therefore we use this instead. + SetParameterMaterialFunction(pythonPath + "/" + pythonModule, "param_r",materialFunctionParameter[i][0]) + SetParameterMaterialFunction(pythonPath + "/" + pythonModule, "param_h",materialFunctionParameter[i][1]) + SetParameterMaterialFunction(pythonPath + "/" + pythonModule, "param_omega_flat",materialFunctionParameter[i][2]) + SetParameterMaterialFunction(pythonPath + "/" + pythonModule, "param_omega_target",materialFunctionParameter[i][3]) + SetParameterMaterialFunction(pythonPath + "/" + pythonModule, "param_theta",materialFunctionParameter[i][4]) + SetParameterMaterialFunction(pythonPath + "/" + pythonModule, "param_beta",materialFunctionParameter[i][5]) + + LOGFILE = outputPath + "/" + pythonModule + "_output" + "_" + str(i) + ".log" + + processList = [] + p = subprocess.Popen(executable + " " + pythonPath + " " + pythonModule + + " -outputPath " + outputPath + + " -gamma " + str(gamma) + + " | tee " + LOGFILE, shell=True) + + # p = subprocess.Popen(executable + " " + pythonPath + " " + pythonModule + # + " -outputPath " + outputPath + # + " -gamma " + str(gamma) + # + " -param_r " + str(materialFunctionParameter[i][0]) + # + " -param_h " + str(materialFunctionParameter[i][1]) + # + " -param_omega_flat " + str(materialFunctionParameter[i][2]) + # + " -param_omega_target " + str(materialFunctionParameter[i][3]) + # + " -phase2_angle " + str(materialFunctionParameter[i][4]) + # + " | tee " + LOGFILE, shell=True) + + p.wait() # wait + processList.append(p) + exit_codes = [p.wait() for p in processList] + # --------------------------------------------------- + # wait here for the result to be available before continuing + # thread.join() + f = open(outputPath+"/parameter.txt", "w") + f.write("r = "+str(materialFunctionParameter[i][0])+"\n") + f.write("h = "+str(materialFunctionParameter[i][1])+"\n") + f.write("omega_flat = "+str(materialFunctionParameter[i][2])+"\n") + f.write("omega_target = "+str(materialFunctionParameter[i][3])+"\n") + f.write("param_beta = "+str(materialFunctionParameter[i][5])+"\n") + f.close() + # diff --git a/experiment/perforated-bilayer/perforated_wood_lower.py b/experiment/perforated-bilayer/perforated_wood_lower.py new file mode 100644 index 0000000000000000000000000000000000000000..95730419f1f1a8d1c8c5dce00f350b429ca24edb --- /dev/null +++ b/experiment/perforated-bilayer/perforated_wood_lower.py @@ -0,0 +1,278 @@ +import math +#from python_matrix_operations import * +import ctypes +import os +import sys +import numpy as np +# import elasticity_toolbox as elast + +class ParameterSet(dict): + def __init__(self, *args, **kwargs): + super(ParameterSet, self).__init__(*args, **kwargs) + self.__dict__ = self + +parameterSet = ParameterSet() +#--------------------------------------------------------------- +############################################# +# Paths +############################################# +# Path for results and logfile +parameterSet.outputPath='/home/klaus/Desktop/Dune_release/dune-microstructure/experiment/perforated-bilayer/results' +parameterSet.baseName= 'perforated_wood_lower' #(needed for Output-Filename) + +# Path for material description +# parameterSet.geometryFunctionPath =experiment/wood-bilayer/ + +#--------------------------------------------------------------- +# Wooden bilayer, https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6191116/#pone.0205607.ref015 +#--- define indicator function +# x[0] : y1-component -1/2 to 1/2 +# x[1] : y2-component -1/2 to 1/2 +# x[2] : x3-component range -1/2 to 1/2 +#--- define indicator function +def indicatorFunction(x): + pRadius = math.sqrt(param_beta/np.pi) + if (x[2]>=(0.5-param_r)): + # if(np.sqrt(x[0]**2 + x[1]**2) < pRadius): #inside perforation + return 1 #Phase1 + else : + if((x[0]**2 + x[1]**2) < pRadius**2): #inside perforation + return 3 #Phase3 + else: + return 2 #Phase2 + +# def indicatorFunction(x): +# factor=1 +# pRadius = 0.25 +# if (x[2]>=(0.5-param_r) and np.sqrt(x[0]**2 + x[1]**2) < pRadius): +# return 3 +# elif((x[2]>=(0.5-param_r))): +# return 1 #Phase1 +# else : +# return 2 #Phase2 + +# # --- Number of material phases +# parameterSet.Phases=3 + +# def indicatorFunction(x): +# factor=1 +# pRadius = 1 +# # if (np.sqrt(x[0]*x[0] + x[1]*x[1]) < pRadius): +# if ((x[0] < 0 and math.sqrt(pow(x[1],2) + pow(x[2],2) ) < pRadius/4.0) or ( 0 < x[0] and math.sqrt(pow(x[1],2) + pow(x[2],2) ) > pRadius/4.0)): +# return 1 +# else : +# return 2 #Phase2 + +# --- Number of material phases +parameterSet.Phases=3 + + +# Parameters of the model +# -- (thickness upper layer) / (thickness) +# param_r = 0.22 +param_r = 0.22 +# -- thickness [meter] +param_h = 0.0053 +# -- moisture content in the flat state [%] +param_omega_flat = 17.17547062 +# -- moisture content in the target state [%] +param_omega_target = 8.959564147 +# -- Drehwinkel +param_theta = 0.0 + +# Design Parameter ratio between perforaton (cylindrical) volume and volume of upper layer +param_beta = 0.3 + +# +# +# +# -- increment of the moisture content +delta_omega=param_omega_target-param_omega_flat +# moisture content for material law +omega=param_omega_target + +# --- Material properties from https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6191116/#pone.0205607.ref015 +# --- for European beech, moisture content omega = 15% +# --- L=direction orthogonal to layering and fibres = orthogonal to wood stem cross-section +# --- T=tangential zu layering +# --- R=orthogonal zu layering +# --- in MPa +# --- Properties are defined by affine function in dependence of moisture content omega via property = b_0+b_1 \omega +# --- coefficients of affine function are contained in the following array +# --- data taken from http://dx.doi.org/10.1016/j.cma.2014.10.031 + +properties_coefficients=np.array([ + # [b_0, b_1] + [2565.6,-59.7], # E_R [MPa] + [885.4, -23.4], # E_T [MPa] + [17136.7,-282.4], # E_L [MPa] + [667.8, -15.19], # G_RT [MPa] + [1482, -15.26], # G_RL [MPa] + [1100, -17.72], # G_TL [MPa] + [0.2933, -0.001012], # nu_TR [1] + [0.383, -0.008722], # nu_LR [1] + [0.3368, -0.009071] # nu_LT [1] + ]) +# Compute actual material properties +E_R = properties_coefficients[0,0]+properties_coefficients[0,1]*omega +E_T = properties_coefficients[1,0]+properties_coefficients[1,1]*omega +E_L = properties_coefficients[2,0]+properties_coefficients[2,1]*omega +G_RT = properties_coefficients[3,0]+properties_coefficients[3,1]*omega +G_LR = properties_coefficients[4,0]+properties_coefficients[4,1]*omega +G_LT = properties_coefficients[5,0]+properties_coefficients[5,1]*omega +nu_TR = properties_coefficients[6,0]+properties_coefficients[6,1]*omega +nu_LR = properties_coefficients[7,0]+properties_coefficients[7,1]*omega +nu_LT = properties_coefficients[8,0]+properties_coefficients[8,1]*omega +# Compute the remaining Poisson ratios +nu_TL=nu_LT*E_T/E_L +nu_RT=nu_TR*E_R/E_T +nu_RL=nu_LR*E_R/E_L +# +# --- differential swelling strain +# --- relation to swelling strain eps: eps=alpha* delta_omega with delta_omega = change of water content in % +alpha_L=0.00011 # PLOS paper +alpha_R=0.00191 # PLOS paper +alpha_T=0.00462 # PLOS paper +# Umrechnen +#alpha_L=(1-1/(1+delta_omega*alpha_L))/delta_omega +#alpha_R=(1-1/(1+delta_omega*alpha_R))/delta_omega +#alpha_T=(1-1/(1+delta_omega*alpha_T))/delta_omega +# --- define geometry + + + +# --- PHASE 1 +# y_1-direction: L +# y_2-direction: T +# x_3-direction: R +# phase1_type="orthotropic" +# materialParameters_phase1 = [E_L,E_T,E_R,G_TL,G_RT,G_RL,nu_LT,nu_LR,nu_TR] +parameterSet.phase1_type="general_anisotropic" +[E_1,E_2,E_3]=[E_L,E_T,E_R] +[nu_12,nu_13,nu_23]=[nu_LT,nu_LR,nu_TR] +[nu_21,nu_31,nu_32]=[nu_TL,nu_RL,nu_RT] +[G_12,G_31,G_23]=[G_LT,G_LR,G_RT] +compliance_S=np.array([[1/E_1, -nu_21/E_2, -nu_31/E_3, 0.0, 0.0, 0.0], + [-nu_12/E_1, 1/E_2, -nu_32/E_3, 0.0, 0.0, 0.0], + [-nu_13/E_1, -nu_23/E_2, 1/E_3, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1/G_23, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 1/G_31, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 1/G_12]]); +materialParameters_phase1 = compliance_S + +def prestrain_phase1(x): + # hB=delta_omega * alpha with delta_omega increment of moisture content and alpha swelling factor. + return [[1/param_h*delta_omega*alpha_L, 0, 0], [0,1/param_h*delta_omega*alpha_T,0], [0,0,1/param_h*delta_omega*alpha_R]] + +# --- PHASE 2 +# y_1-direction: R +# y_2-direction: L +# x_3-direction: T +parameterSet.phase2_type="general_anisotropic" +[E_1,E_2,E_3]=[E_R,E_L,E_T] +[nu_12,nu_13,nu_23]=[nu_RL,nu_RT,nu_LT] +[nu_21,nu_31,nu_32]=[nu_LR,nu_TR,nu_TL] +[G_12,G_31,G_23]=[G_LR,G_RT,G_LT] +compliance_S=np.array([[1/E_1, -nu_21/E_2, -nu_31/E_3, 0.0, 0.0, 0.0], + [-nu_12/E_1, 1/E_2, -nu_32/E_3, 0.0, 0.0, 0.0], + [-nu_13/E_1, -nu_23/E_2, 1/E_3, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1/G_23, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 1/G_31, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 1/G_12]]); +materialParameters_phase2 = compliance_S +def prestrain_phase2(x): + return [[1/param_h*delta_omega*alpha_R, 0, 0], [0,1/param_h*delta_omega*alpha_L,0], [0,0,1/param_h*delta_omega*alpha_T]] + +#Rotation um 2. Achse (= L) +parameterSet.phase2_axis = 1 +# phase2_angle = param_theta +# -- Drehwinkel +parameterSet.phase2_angle = param_theta + + +# --- PHASE 3 +parameterSet.phase3_type="isotropic" +epsilon = 1e-8 +materialParameters_phase3 = [epsilon, epsilon] + +def prestrain_phase3(x): + return [[0, 0, 0], [0,0,0], [0,0,0]] + +# # --- PHASE 3 = Phase 1 gedreht +# # y_1-direction: L +# # y_2-direction: R +# # x_3-direction: T +# parameterSet.phase3_type="general_anisotropic" +# # Drehung um theta um Achse 2 = x_3-Achse +# N=elast.rotation_matrix_compliance(2,param_theta) +# materialParameters_phase3 = np.dot(np.dot(N,materialParameters_phase1),N.T) +# materialParameters_phase3 = 0.5*(materialParameters_phase3.T+materialParameters_phase3) +# # rotation of strain +# def prestrain_phase3(x): +# return elast.voigt_to_strain(np.dot(elast.rotation_matrix_compliance(2,param_theta),np.dot(elast.strain_to_voigt(np.array(prestrain_phase1(x))),N.T))).tolist() + + + +# --- Choose scale ratio gamma: +parameterSet.gamma=1.0 + + + + +############################################# +# Grid parameters +############################################# +## numLevels : Number of Levels on which solution is computed. starting with a 2x2x2 cube mesh. +## {start,finish} computes on all grid from 2^(start) to 2^finish refinement +#---------------------------------------------------- +parameterSet.numLevels= '3 3' # computes all levels from first to second entry + + +############################################# +# Assembly options +############################################# +parameterSet.set_IntegralZero = 1 #(default = false) +parameterSet.set_oneBasisFunction_Zero = 1 #(default = false) +#parameterSet.arbitraryLocalIndex = 7 #(default = 0) +#parameterSet.arbitraryElementNumber = 3 #(default = 0) + +############################################# +# Solver Options, Type: #1: CG - SOLVER , #2: GMRES - SOLVER, #3: QR - SOLVER (default), #4: UMFPACK - SOLVER +############################################# +parameterSet.Solvertype = 3 # recommended to use iterative solver (e.g GMRES) for finer grid-levels +parameterSet.Solver_verbosity = 0 #(default = 2) degree of information for solver output + + +############################################# +# Write/Output options #(default=false) +############################################# +# --- (Optional output) write Material / prestrain / Corrector functions to .vtk-Files: +parameterSet.write_materialFunctions = 1 # VTK indicator function for material/prestrain definition +#parameterSet.write_prestrainFunctions = 1 # VTK norm of B (currently not implemented) + +# --- (Additional debug output) +parameterSet.print_debug = 0 #(default=false) + +# --- Write Correctos to VTK-File: +parameterSet.write_VTK = 1 + +# The grid can be refined several times for a higher resolution in the VTK-file. +parameterSet.subsamplingRefinement = 2 + +# --- (Optional output) L2Error, integral mean: +#parameterSet.write_L2Error = 1 +#parameterSet.write_IntegralMean = 1 + +# --- check orthogonality (75) from paper: +parameterSet.write_checkOrthogonality = 0 + +# --- Write corrector-coefficients to log-File: +#parameterSet.write_corrector_phi1 = 1 +#parameterSet.write_corrector_phi2 = 1 +#parameterSet.write_corrector_phi3 = 1 + +# --- Print Condition number of matrix (can be expensive): +#parameterSet.print_conditionNumber= 1 #(default=false) + +# --- write effective quantities to Matlab-folder for symbolic minimization: +parameterSet.write_toMATLAB = 1 # writes effective quantities to .txt-files QMatrix.txt and BMatrix.txt diff --git a/experiment/perforated-bilayer/perforated_wood_upper.py b/experiment/perforated-bilayer/perforated_wood_upper.py new file mode 100644 index 0000000000000000000000000000000000000000..9316c2b1dadd3031a71b6c0e1cc073da8042b80b --- /dev/null +++ b/experiment/perforated-bilayer/perforated_wood_upper.py @@ -0,0 +1,278 @@ +import math +#from python_matrix_operations import * +import ctypes +import os +import sys +import numpy as np +# import elasticity_toolbox as elast + +class ParameterSet(dict): + def __init__(self, *args, **kwargs): + super(ParameterSet, self).__init__(*args, **kwargs) + self.__dict__ = self + +parameterSet = ParameterSet() +#--------------------------------------------------------------- +############################################# +# Paths +############################################# +# Path for results and logfile +parameterSet.outputPath='/home/klaus/Desktop/Dune_release/dune-microstructure/experiment/perforated-bilayer/results' +parameterSet.baseName= 'perforated_wood_upper' #(needed for Output-Filename) + +# Path for material description +# parameterSet.geometryFunctionPath =experiment/wood-bilayer/ + +#--------------------------------------------------------------- +# Wooden bilayer, https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6191116/#pone.0205607.ref015 +#--- define indicator function +# x[0] : y1-component -1/2 to 1/2 +# x[1] : y2-component -1/2 to 1/2 +# x[2] : x3-component range -1/2 to 1/2 +#--- define indicator function +def indicatorFunction(x): + pRadius = math.sqrt(param_beta/np.pi) + if (x[2]>=(0.5-param_r)): + # if(np.sqrt(x[0]**2 + x[1]**2) < pRadius): #inside perforation + if((x[0]**2 + x[1]**2) < pRadius**2): #inside perforation + return 3 #Phase3 + else: + return 1 #Phase1 + else : + return 2 #Phase2 + +# def indicatorFunction(x): +# factor=1 +# pRadius = 0.25 +# if (x[2]>=(0.5-param_r) and np.sqrt(x[0]**2 + x[1]**2) < pRadius): +# return 3 +# elif((x[2]>=(0.5-param_r))): +# return 1 #Phase1 +# else : +# return 2 #Phase2 + +# # --- Number of material phases +# parameterSet.Phases=3 + +# def indicatorFunction(x): +# factor=1 +# pRadius = 1 +# # if (np.sqrt(x[0]*x[0] + x[1]*x[1]) < pRadius): +# if ((x[0] < 0 and math.sqrt(pow(x[1],2) + pow(x[2],2) ) < pRadius/4.0) or ( 0 < x[0] and math.sqrt(pow(x[1],2) + pow(x[2],2) ) > pRadius/4.0)): +# return 1 +# else : +# return 2 #Phase2 + +# --- Number of material phases +parameterSet.Phases=3 + + +# Parameters of the model +# -- (thickness upper layer) / (thickness) +# param_r = 0.22 +param_r = 0.22 +# -- thickness [meter] +param_h = 0.0053 +# -- moisture content in the flat state [%] +param_omega_flat = 17.17547062 +# -- moisture content in the target state [%] +param_omega_target = 8.959564147 +# -- Drehwinkel +param_theta = 0.0 + +# Design Parameter ratio between perforaton (cylindrical) volume and volume of upper layer +param_beta = 0.3 + +# +# +# +# -- increment of the moisture content +delta_omega=param_omega_target-param_omega_flat +# moisture content for material law +omega=param_omega_target + +# --- Material properties from https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6191116/#pone.0205607.ref015 +# --- for European beech, moisture content omega = 15% +# --- L=direction orthogonal to layering and fibres = orthogonal to wood stem cross-section +# --- T=tangential zu layering +# --- R=orthogonal zu layering +# --- in MPa +# --- Properties are defined by affine function in dependence of moisture content omega via property = b_0+b_1 \omega +# --- coefficients of affine function are contained in the following array +# --- data taken from http://dx.doi.org/10.1016/j.cma.2014.10.031 + +properties_coefficients=np.array([ + # [b_0, b_1] + [2565.6,-59.7], # E_R [MPa] + [885.4, -23.4], # E_T [MPa] + [17136.7,-282.4], # E_L [MPa] + [667.8, -15.19], # G_RT [MPa] + [1482, -15.26], # G_RL [MPa] + [1100, -17.72], # G_TL [MPa] + [0.2933, -0.001012], # nu_TR [1] + [0.383, -0.008722], # nu_LR [1] + [0.3368, -0.009071] # nu_LT [1] + ]) +# Compute actual material properties +E_R = properties_coefficients[0,0]+properties_coefficients[0,1]*omega +E_T = properties_coefficients[1,0]+properties_coefficients[1,1]*omega +E_L = properties_coefficients[2,0]+properties_coefficients[2,1]*omega +G_RT = properties_coefficients[3,0]+properties_coefficients[3,1]*omega +G_LR = properties_coefficients[4,0]+properties_coefficients[4,1]*omega +G_LT = properties_coefficients[5,0]+properties_coefficients[5,1]*omega +nu_TR = properties_coefficients[6,0]+properties_coefficients[6,1]*omega +nu_LR = properties_coefficients[7,0]+properties_coefficients[7,1]*omega +nu_LT = properties_coefficients[8,0]+properties_coefficients[8,1]*omega +# Compute the remaining Poisson ratios +nu_TL=nu_LT*E_T/E_L +nu_RT=nu_TR*E_R/E_T +nu_RL=nu_LR*E_R/E_L +# +# --- differential swelling strain +# --- relation to swelling strain eps: eps=alpha* delta_omega with delta_omega = change of water content in % +alpha_L=0.00011 # PLOS paper +alpha_R=0.00191 # PLOS paper +alpha_T=0.00462 # PLOS paper +# Umrechnen +#alpha_L=(1-1/(1+delta_omega*alpha_L))/delta_omega +#alpha_R=(1-1/(1+delta_omega*alpha_R))/delta_omega +#alpha_T=(1-1/(1+delta_omega*alpha_T))/delta_omega +# --- define geometry + + + +# --- PHASE 1 +# y_1-direction: L +# y_2-direction: T +# x_3-direction: R +# phase1_type="orthotropic" +# materialParameters_phase1 = [E_L,E_T,E_R,G_TL,G_RT,G_RL,nu_LT,nu_LR,nu_TR] +parameterSet.phase1_type="general_anisotropic" +[E_1,E_2,E_3]=[E_L,E_T,E_R] +[nu_12,nu_13,nu_23]=[nu_LT,nu_LR,nu_TR] +[nu_21,nu_31,nu_32]=[nu_TL,nu_RL,nu_RT] +[G_12,G_31,G_23]=[G_LT,G_LR,G_RT] +compliance_S=np.array([[1/E_1, -nu_21/E_2, -nu_31/E_3, 0.0, 0.0, 0.0], + [-nu_12/E_1, 1/E_2, -nu_32/E_3, 0.0, 0.0, 0.0], + [-nu_13/E_1, -nu_23/E_2, 1/E_3, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1/G_23, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 1/G_31, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 1/G_12]]); +materialParameters_phase1 = compliance_S + +def prestrain_phase1(x): + # hB=delta_omega * alpha with delta_omega increment of moisture content and alpha swelling factor. + return [[1/param_h*delta_omega*alpha_L, 0, 0], [0,1/param_h*delta_omega*alpha_T,0], [0,0,1/param_h*delta_omega*alpha_R]] + +# --- PHASE 2 +# y_1-direction: R +# y_2-direction: L +# x_3-direction: T +parameterSet.phase2_type="general_anisotropic" +[E_1,E_2,E_3]=[E_R,E_L,E_T] +[nu_12,nu_13,nu_23]=[nu_RL,nu_RT,nu_LT] +[nu_21,nu_31,nu_32]=[nu_LR,nu_TR,nu_TL] +[G_12,G_31,G_23]=[G_LR,G_RT,G_LT] +compliance_S=np.array([[1/E_1, -nu_21/E_2, -nu_31/E_3, 0.0, 0.0, 0.0], + [-nu_12/E_1, 1/E_2, -nu_32/E_3, 0.0, 0.0, 0.0], + [-nu_13/E_1, -nu_23/E_2, 1/E_3, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1/G_23, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 1/G_31, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 1/G_12]]); +materialParameters_phase2 = compliance_S +def prestrain_phase2(x): + return [[1/param_h*delta_omega*alpha_R, 0, 0], [0,1/param_h*delta_omega*alpha_L,0], [0,0,1/param_h*delta_omega*alpha_T]] + +#Rotation um 2. Achse (= L) +parameterSet.phase2_axis = 1 +# phase2_angle = param_theta +# -- Drehwinkel +parameterSet.phase2_angle = param_theta + + +# --- PHASE 3 +parameterSet.phase3_type="isotropic" +epsilon = 1e-8 +materialParameters_phase3 = [epsilon, epsilon] + +def prestrain_phase3(x): + return [[0, 0, 0], [0,0,0], [0,0,0]] + +# # --- PHASE 3 = Phase 1 gedreht +# # y_1-direction: L +# # y_2-direction: R +# # x_3-direction: T +# parameterSet.phase3_type="general_anisotropic" +# # Drehung um theta um Achse 2 = x_3-Achse +# N=elast.rotation_matrix_compliance(2,param_theta) +# materialParameters_phase3 = np.dot(np.dot(N,materialParameters_phase1),N.T) +# materialParameters_phase3 = 0.5*(materialParameters_phase3.T+materialParameters_phase3) +# # rotation of strain +# def prestrain_phase3(x): +# return elast.voigt_to_strain(np.dot(elast.rotation_matrix_compliance(2,param_theta),np.dot(elast.strain_to_voigt(np.array(prestrain_phase1(x))),N.T))).tolist() + + + +# --- Choose scale ratio gamma: +parameterSet.gamma=1.0 + + + + +############################################# +# Grid parameters +############################################# +## numLevels : Number of Levels on which solution is computed. starting with a 2x2x2 cube mesh. +## {start,finish} computes on all grid from 2^(start) to 2^finish refinement +#---------------------------------------------------- +parameterSet.numLevels= '3 3' # computes all levels from first to second entry + + +############################################# +# Assembly options +############################################# +parameterSet.set_IntegralZero = 1 #(default = false) +parameterSet.set_oneBasisFunction_Zero = 1 #(default = false) +#parameterSet.arbitraryLocalIndex = 7 #(default = 0) +#parameterSet.arbitraryElementNumber = 3 #(default = 0) + +############################################# +# Solver Options, Type: #1: CG - SOLVER , #2: GMRES - SOLVER, #3: QR - SOLVER (default), #4: UMFPACK - SOLVER +############################################# +parameterSet.Solvertype = 3 # recommended to use iterative solver (e.g GMRES) for finer grid-levels +parameterSet.Solver_verbosity = 0 #(default = 2) degree of information for solver output + + +############################################# +# Write/Output options #(default=false) +############################################# +# --- (Optional output) write Material / prestrain / Corrector functions to .vtk-Files: +parameterSet.write_materialFunctions = 1 # VTK indicator function for material/prestrain definition +#parameterSet.write_prestrainFunctions = 1 # VTK norm of B (currently not implemented) + +# --- (Additional debug output) +parameterSet.print_debug = 0 #(default=false) + +# --- Write Correctos to VTK-File: +parameterSet.write_VTK = 1 + +# The grid can be refined several times for a higher resolution in the VTK-file. +parameterSet.subsamplingRefinement = 2 + +# --- (Optional output) L2Error, integral mean: +#parameterSet.write_L2Error = 1 +#parameterSet.write_IntegralMean = 1 + +# --- check orthogonality (75) from paper: +parameterSet.write_checkOrthogonality = 0 + +# --- Write corrector-coefficients to log-File: +#parameterSet.write_corrector_phi1 = 1 +#parameterSet.write_corrector_phi2 = 1 +#parameterSet.write_corrector_phi3 = 1 + +# --- Print Condition number of matrix (can be expensive): +#parameterSet.print_conditionNumber= 1 #(default=false) + +# --- write effective quantities to Matlab-folder for symbolic minimization: +parameterSet.write_toMATLAB = 1 # writes effective quantities to .txt-files QMatrix.txt and BMatrix.txt