"""Output file: Homogeneous (fictitious) reference material.
This module includes the class associated with the output file where data
associated with the homogeneous (fictitious) reference material is stored.
Classes
-------
RefMatOutput
Output file: Homogeneous (fictitious) reference material data
"""
#
# Modules
# =============================================================================
# Third-party
import numpy as np
# Local
from ioput.incoutputfiles.interface import IncrementalOutputFile
import tensor.matrixoperations as mop
#
# Authorship & Credits
# =============================================================================
__author__ = 'Bernardo Ferreira (bernardo_ferreira@brown.edu)'
__credits__ = ['Bernardo Ferreira', ]
__status__ = 'Stable'
# =============================================================================
#
# =============================================================================
[docs]class RefMatOutput(IncrementalOutputFile):
"""Output file: Homogeneous (fictitious) reference material data.
Attributes
----------
_file_path : str
Output file path.
_header : list[str]
List containing the header of each column (str).
_col_width : int
Output file column width.
_n_dim : int
Problem number of spatial dimensions.
_comp_order_sym : list[str]
Strain/Stress components symmetric order.
_comp_order_nsym : list[str]
Strain/Stress components nonsymmetric order.
Methods
-------
init_file(self)
Open reference material output file and write file header.
write_mat(self, inc, ref_material, hom_strain_mf, hom_stress_mf, \
eff_tangent_mf=None, farfield_strain_mf=None, \
applied_mac_load_strain_mf=None)
Write reference material output file.
rewind_file(self, rewind_inc)
Rewind reference material output file.
"""
[docs] def __init__(self, file_path, strain_formulation, problem_type,
self_consistent_scheme='regression',
ref_output_mode='converged'):
"""Constructor.
Parameters
----------
file_path : str
Output file path.
strain_formulation: {'infinitesimal', 'finite'}
Problem strain formulation.
problem_type : int
Problem type: 2D plane strain (1), 2D plane stress (2),
2D axisymmetric (3) and 3D (4).
self_consistent_scheme : {'regression',}, default='regression'
Self-consistent scheme to update the elastic reference material
properties.
ref_output_mode : {'iterative', 'converged'}, default='converged'
Output mode:
* 'iterative' : outputs the reference material quantities at \
every self-consistent scheme iteration
* 'converged' : outputs the reference material quantities that \
converged at each loading increment
"""
self._file_path = file_path
self._strain_formulation = strain_formulation
self._problem_type = problem_type
self._self_consistent_scheme = self_consistent_scheme
self._ref_output_mode = ref_output_mode
# Get problem type parameters
n_dim, comp_order_sym, comp_order_nsym = \
mop.get_problem_type_parameters(problem_type)
self._n_dim = n_dim
self._comp_order_sym = comp_order_sym
self._comp_order_nsym = comp_order_nsym
# Set reference material output file header
self._header = ['Increment', 'SCS Iteration',
'E_ref', 'v_ref',
'strain0_11', 'strain0_21', 'strain0_31',
'strain0_12', 'strain0_22', 'strain0_32',
'strain0_13', 'strain0_23', 'strain0_33',
'strain_0_rdiff', 'rel_scs_cost', 'tangent_rdiff']
# Set column width
self._col_width = max(16, max([len(x) for x in self._header]) + 2)
# -------------------------------------------------------------------------
[docs] def init_file(self):
"""Open output file and write file header."""
# Set reference material elastic properties initial output
properties_init = (0.0, 0.0)
# Set far-field strain initial output
strain_init = 9*[0.0, ]
if self._strain_formulation == 'finite':
strain_init[0] = 1.0
strain_init[4] = 1.0
strain_init[8] = 1.0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Open output file (write mode)
refm_file = open(self._file_path, 'w')
# Set output file header format structure
write_list = [
'{:>9s}'.format(self._header[0]) + ' '
+ '{:>13s}'.format(self._header[1])
+ ''.join([('{:>' + str(self._col_width) + 's}').format(x)
for x in self._header[2:]]),
'\n' + '{:>9d}'.format(0) + ' ' + '{:>13d}'.format(0)
+ ''.join([('{:>' + str(self._col_width) + '.8e}').format(x)
for x in properties_init])
+ ''.join([('{:>' + str(self._col_width) + '.8e}').format(x)
for x in strain_init])
+ ''.join([('{:>' + str(self._col_width) + '.8e}').format(0)
for x in self._header[13:]]), ]
# Write output file header
refm_file.writelines(write_list)
# Close output file
refm_file.close()
# -------------------------------------------------------------------------
[docs] def write_file(self, inc, ref_material, hom_strain_mf, hom_stress_mf,
farfield_strain_mf, applied_mac_load_strain_mf,
eff_tangent_mf=None):
"""Write output file.
Parameters
----------
inc : int
Loading increment.
ref_material : ElasticReferenceMaterial
Elastic reference material.
hom_strain_mf : numpy.ndarray (1d)
Homogenized strain tensor (matricial form): infinitesimal strain
tensor (infinitesimal strains) or deformation gradient (finite
strains).
hom_stress_mf : numpy.ndarray (1d)
Homogenized stress tensor (matricial form): Cauchy stress tensor
(infinitesimal strains) or first Piola-Kirchhoff stress tensor
(finite strains).
farfield_strain_mf : numpy.ndarray (1d)
Far-field strain tensor (matricial form).
applied_mac_load_strain_mf : numpy.ndarray (1d)
Prescribed loading strain tensor (matricial form).
eff_tangent_mf : numpy.ndarray (2d), default=None
CRVE effective material tangent modulus (matricial form).
"""
# Set strain/stress components order according to problem strain
# formulation
if self._strain_formulation == 'infinitesimal':
comp_order = self._comp_order_sym
elif self._strain_formulation == 'finite':
comp_order = self._comp_order_nsym
else:
raise RuntimeError('Unknown problem strain formulation.')
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get self-consistent scheme iteration counter
scs_iter = ref_material.get_scs_iter()
# Get elastic reference material properties
ref_material_properties = ref_material.get_material_properties()
# Get elastic reference material tangent modulus (matricial form)
ref_elastic_tangent_mf = ref_material.get_elastic_tangent_mf()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# When the problem type corresponds to a 2D analysis, build the 3D
# far-field strain tensor considering the appropriate out-of-plane
# strain component (output purpose only).
farfield_strain = mop.get_tensor_from_mf(farfield_strain_mf,
self._n_dim, comp_order)
out_farfield_strain = np.zeros((3, 3))
if self._problem_type == 1:
out_farfield_strain[0:2, 0:2] = farfield_strain
if self._strain_formulation == 'finite':
out_farfield_strain[2, 2] = 1.0
else:
out_farfield_strain[:, :] = farfield_strain
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Compute norm of difference between the far-field strain tensor and
# prescribed loading strain tensor and then normalize it to obtain
# relative measure
diff_norm = np.linalg.norm(farfield_strain_mf
- applied_mac_load_strain_mf)
rel_diff_farfield = \
diff_norm/np.linalg.norm(applied_mac_load_strain_mf)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Compute self-consistent scheme normalized cost function
if self._self_consistent_scheme == 'regression':
# Compute regression-based scheme cost function
scs_cost = np.linalg.norm(hom_stress_mf
- np.matmul(ref_elastic_tangent_mf,
hom_strain_mf))**2
# Normalize cost function
rel_scs_cost = scs_cost/(np.linalg.norm(hom_stress_mf)**2)
else:
# If self-consistent scheme cost function computation is not
# implemented, output normalized cost function value as infinite
rel_scs_cost = 0.0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Compute norm of difference between the effective tangent modulus and
# the reference material tangent modulus and then normalize it to
# obtain a relative measure
if eff_tangent_mf is not None:
diff_norm = np.linalg.norm(ref_elastic_tangent_mf - eff_tangent_mf)
rel_diff_tangent = diff_norm/np.linalg.norm(eff_tangent_mf)
else:
rel_diff_tangent = 0.0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set reference material format structure
inc_data = [inc, scs_iter,
ref_material_properties['E'], ref_material_properties['v'],
out_farfield_strain[0, 0], out_farfield_strain[1, 0],
out_farfield_strain[2, 0], out_farfield_strain[0, 1],
out_farfield_strain[1, 1], out_farfield_strain[2, 1],
out_farfield_strain[0, 2], out_farfield_strain[1, 2],
out_farfield_strain[2, 2],
rel_diff_farfield, rel_scs_cost, rel_diff_tangent]
write_list = [
'\n' + '{:>9d}'.format(inc) + ' ' + '{:>13d}'.format(scs_iter)
+ ''.join([('{:>' + str(self._col_width) + '.8e}').format(x)
for x in inc_data[2:]])]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Open reference material output file and read lines (read)
file_lines = open(self._file_path, 'r').readlines()
# Update reference material output file according to output mode
if self._ref_output_mode == 'iterative':
# If loading increment is being repeated for some reason, then
# clear the associated data and append the first iteration.
# Otherwise append iteration belonging to the current loading
# increment
if len(file_lines) > 1 and int(file_lines[-1].split()[0]) == inc \
and not scs_iter > int(file_lines[-1].split()[1]):
# If loading increment is being repeated for some reason, then
# clear the associated data
del file_lines[-(int(file_lines[-1].split()[1]) + 1):]
file_lines += write_list[0][1:]
else:
file_lines += write_list[0]
else:
# If is the same loading increment, then replace the last
# iteration. Otherwise append iteration belonging to new loading
# increment
if len(file_lines) > 1 and int(file_lines[-1].split()[0]) == inc:
file_lines[-1] = write_list[0][1:]
else:
file_lines += write_list[0]
# Open output file (write mode) and write data
open(self._file_path, 'w').writelines(file_lines)
# -------------------------------------------------------------------------
[docs] def rewind_file(self, rewind_inc):
"""Rewind output file.
Parameters
----------
rewind_inc : int
Increment associated with the rewind state.
"""
# Open reference material output file and read lines (read)
file_lines = open(self._file_path, 'r').readlines()
# Rewind reference material output file according to output mode
if self._ref_output_mode == 'iterative':
# Loop over file lines
for i in range(1, len(file_lines)):
# Get file line
line = file_lines[i]
# Check for increment after increment associated with rewind
# state
if int(line.split()[0]) == rewind_inc + 1:
# Set output file last line
last_line = i - 1
break
else:
# Set output file last line
last_line = 1 + rewind_inc
# Remove next line character
file_lines[last_line] = file_lines[last_line][:-1]
# Open output file (write mode) and write data
open(self._file_path, 'w').writelines(file_lines[: last_line + 1])