pyoptmat.experiments: storing, formatting, and saving experimental data

Various routines for dealing with generating input and processing output for abstracted records of experimental tests.

These routines do things like:
  • Convert simplified descriptions of tests into strain/strain time histories that the models can use

  • Generate random experiments and the corresponding inputs

The actual deterministic and statistical fitting routines expect data in a common format. There are a few conditions on the input test data:

  1. You have to sample all tests with the same number of time points (ntime).

  2. You have to provide the full, correct history of the input conditions. For strain controlled experiments this is the full history of test time, strain, and temperature. For stress control it is the full history of time, stress, and temperature.

  3. You do not have to provide the full results history. That is, the fit routines can accommodate some types of abstracted test data, like maximum stress as a function of cycles for strain-controlled cyclic tests. The convert_results function can then convert a full (simulated) results history to the right abstracted format for comparison to the test data.

The fitting routines rely on five tensors with the following format:

  • data (3, ntime, nexp): the input experimental conditions. The first index contains the experimental time, temperature, and strain history for strain controlled tests and the experimental time, temperature and stress history for stress controlled tests

  • results (ntime, nexp): the (potentially abstracted) experimental results. For example, this could be the stress history for a tensile test or the strain history for a creep test. The specific requirements for certain tests types are described below.

  • cycles (ntime, nexp): the cycle counts for cyclic tests or an integer used to indicate features of the experiment for other test types. Specific requirements are given below.

  • types (nexp,): an integer giving the test type (see list below)

  • control (nexp,): 0 for strain control, 1 for stress control

The current test types are:

  1. “tension” – uniaxial, monotonic tension or compression test

  2. “relaxation” – stress relaxation test

  3. “strain_cyclic” – strain controlled cyclic (i.e. creep or creep-fatigue)

  4. “creep” – a creep test

  5. “stress_cyclic” – a stress controlled cyclic test

  6. “abstract_tensile” – tension tests where only the yield strength and ultimate tensile strength are known

  7. “direct_data” – the full results history is known and provided

The pyoptmat.experiments.load_results() function provides a way to load data for this type from an xarray format. The same tensors are stored in the xarray structure, however the descriptive string names for the tests are used and “strain” or “stress” is used instead of 0 and 1 to indicate the control type. Additional metadata can be stored in the xarray format with source information, heat ID, etc.

pyoptmat.experiments.convert_results(results, cycles, types)

Process a raw results vector to our common format based on test type

Parameters:
  • results (torch.tensor) – raw results data (ntime, nexperiment)

  • cycles (torch.tensor) – cycle counts (ntime, nexperiment)

  • types (torch.tensor) – test types (nexperiment,)

Returns:

tensor of processed results

Return type:

torch.tensor

pyoptmat.experiments.format_abstract_tensile(cycles, predictions)

Format abstracted tensile test data, where only the yield strength and ultimate tensile strength are available.

This method relies on the input cycles being: * 0: in the elastic regime * 1: for the first 1/2 of the remaining time points outside of the elastic regime * 2: for the second 1/2 of the remaining time points.

The inputs are the full stress history. This function:

  • Cycle 0: overwrite with zeros

  • Cycle 1: overwrite with the first value in cycle 1

  • Cycle 2: overwrite with the maximum stress

Parameters:
  • cycles (torch.tensor) – cycle count

  • predictions (torch.tensor) – input to format

Returns:

tensor of processed results

Return type:

torch.tensor

pyoptmat.experiments.format_cyclic(cycles, predictions)

Format a generic cyclic test – works for both stress and strain control

Input data are stresses for strain control and strains for stress control.

We format this as a “block” – the values for each cycle are replaced by the maximum value within the cycle

Parameters:
  • cycles (torch.tensor) – cycle count/listing

  • predictions (torch.tensor) – input data

Returns:

processed results

Return type:

torch.tensor

pyoptmat.experiments.format_direct_data(cycles, predictions)

Format direct stress/strain results

For this test type cycles just equals 0 for all time steps

This function does nothing, it just returns predictions

Parameters:
  • cycles (torch.tensor) – cycle count

  • predictions (torch.tensor) – input to format

Returns:

tensor of processed results

Return type:

torch.tensor

pyoptmat.experiments.format_relaxation(cycles, predictions)

Format stress relaxation test data to our “post-processed” form for comparison. This works for both creep and stress relaxation tests.

Input data are stresses for stress relaxation and strains for creep

Cycle 0 indicates the loading part of the test, cycle 1 is the hold

Zero out the loading results, replace the relaxation results with the normalized (subtract t=0) curve

Parameters:
  • cycles (torch.tensor) – cycle count/listing

  • predictions (torch.tensor) – input data

Returns:

processed results

Return type:

torch.tensor

pyoptmat.experiments.format_tensile(cycles, predictions)

Format tension test data to our “post-processed” form for comparison

Input data are stresses for this test type

Cycles are all 0

This function doesn’t do anything, just returns predictions

Parameters:
  • cycles (torch.tensor) – cycle count/listing

  • predictions (torch.tensor) – input data

Returns:

processed results

Return type:

torch.tensor

pyoptmat.experiments.generate_random_cycle(max_strain=[0, 0.02], R=[-1, 1], strain_rate=[0.001, 1e-05], tension_hold=[0, 3600.0], compression_hold=[0, 600])

Generate a random cycle in the provided ranges

Keyword Arguments:
  • max_strain (list) – range of the maximum strains

  • R (list) – range of R ratios

  • strain_rate (list) – range of loading strain rates

  • tension_hold (list) – range of tension hold times

  • compression_hold (list) – range of compression hold times

Returns:

dictionary describing cycle, described below

Return type:

dict

  • "max_strain" – maximum strain value

  • "R" – R ratio \(\frac{max}{min}\)

  • "strain_rate" – strain rate during load/unload

  • "tension_hold" – hold on the tension end of the cycle

  • "compression_hold" – hold on the compressive end of the cycle

pyoptmat.experiments.generate_random_tension(strain_rate=[1e-06, 0.01], max_strain=0.2)

Generate a random tension test condition in the provided ranges

Keyword Arguments:
  • strain_rate (list) – Range of strain rates

  • max_strain (float) – Maximum strain to simulate

Returns:

dictionary with "max_strain"

and "strain_rate"

Return type:

dict

pyoptmat.experiments.load_results(xdata, device=device(type='cpu'))

Load experimental data from xarray into torch tensors

Parameters:

xdata (xarray.DataArray) – xarray data structure

Keyword Arguments:

device (torch.device) – the device to dump the resulting arrays on

Returns:

see below

Return type:

tuple

This function returns a tuple of five tensors

data (3, ntime, nexperiment)

The initial index are the experimental (times, temperatures, idata) For strain controlled tests idata is strain For stress controlled tests idata is stress

results (ntime, nexperiment)

For strain controlled tests this is stress For stress controlled tests this is strain

cycles (ntime, nexperiment)

Cycle count for all tests

types (nexperiment,)

Experiment types, converted to integers per the dicts above

control (nexperiment,)

Maps the string control type (“strain” or “stress”) to an integer using the dict above

pyoptmat.experiments.make_creep_tests(stress, temperature, rate, hold_times, nsteps_load, nsteps_hold, logspace=False)

Produce creep test input (time,stress,temperature) given tensor inputs for the target stress, target temperature, loading rate

Parameters:
  • stress (torch.tensor) – 1D tensor of target stresses

  • temperature (torch.tensor) – 1D tensor of target temperature

  • rate (torch.tensor) – 1D tensor of target rates

  • hold_times (torch.tensor) – 1D tensor of hold times

  • nsteps_load (torch.tensor) – number of time steps to load up the sample

  • nsteps_hold (torch.tensor) – number of time steps to hold the sample

Keyword Arguments:

logspace (bool) – log-space time increments during holds

Returns:

tuple of

(times, strains, temperatures, cycles)

Return type:

tuple

pyoptmat.experiments.make_tension_tests(rates, temperatures, elimits, nsteps)

Produce tension test (time,strain,temperature) history blocks given tensor inputs for the strain rates, temperatures, and maximum strain of each test

Parameters:
  • rates (torch.tensor) – 1D tensor giving the strain rate of each test

  • temperaturess (torch.tensor) – 1D tensor giving the constant temperature of each test

  • elimits (torch.tensor) – 1D tensor giving the maximum strain of each test

  • nsteps (torch.tensor) – integer number of steps

Returns:

tuple of

(times, strains, temperatures, cycles)

Return type:

tuple

pyoptmat.experiments.sample_cycle_normalized_times(cycle, N, nload=10, nhold=10)

Sample a cyclic test at a normalized series of times

Take a random cycle dictionary and expand into discrete times, strains samples where times are the actual, physical times, given over the fixed phases

  • \(0 \rightarrow t_{phase}\) – tension load

  • \(t_{phase} \rightarrow 2 t_{phase}\) – tension hold

  • \(2 t_{phase} \rightarrow 3 t_{phase}\) – unload

  • \(3 t_{phase} \rightarrow 4 t_{phase}\) – compression load

  • \(4 t_{phase} \rightarrow 5 t_{phase}\) – compression hold

  • \(5 t_{phase} \rightarrow 6 t_{phase}\) – unload

This pattern repeats for N cycles

Parameters:
  • cycle (dict) – dictionary defining the load cycle

  • N (int) – number of repeats to include in the history

Keyword Arguments:
  • nload (int) – number of steps to use for the load time

  • nhold (int) – number of steps to use for the hold time

pyoptmat.experiments.sample_tension(test, nsteps=50)

Generate the times and strains for a tensile test

Parameters:

test (dict) – Dictionary defining the test case

Keyword Arguments:

nsteps (int) – Number of steps to sample

Returns:

tuple of (times, strains)

Return type:

tuple