├── LICENSE ├── README.md ├── data └── dataset.zip ├── rnn.jpg └── src ├── RNN_one2one.pdf ├── RNN_viscoelasticity_3D_2LSTM_1000epochs.pdf └── myLSTMclass.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 GuangC-iScience 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Recurrent neural networks (RNNs) learn the constitutive law of viscoelasticity 2 | RNN-viscoelasticity model development 3 | 4 | ![RNN-viscoelasticity](./rnn.jpg) 5 | 6 | # Content 7 | - data: the dataset for RNN-viscoelasticity model development 8 | - src: the source code for model development and construction of one-to-one architecture from the trained model 9 | 10 | # How to cite 11 | Chen, Guang. "Recurrent neural networks (RNNs) learn the constitutive law of viscoelasticity." Computational Mechanics 67.3 (2021): 1009-1019. https://doi.org/10.1007/s00466-021-01981-y. 12 | 13 | # Related 14 | More details on the computational mechanics aspect can be found at my [website](https://www.gchenlab.com/viscoelasticity1-infinitesimal-strain/) 15 | -------------------------------------------------------------------------------- /data/dataset.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanogchen/rnn-viscoelasticity/e0de2285470d9b08b4aa38b35fb467166a649aab/data/dataset.zip -------------------------------------------------------------------------------- /rnn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanogchen/rnn-viscoelasticity/e0de2285470d9b08b4aa38b35fb467166a649aab/rnn.jpg -------------------------------------------------------------------------------- /src/RNN_one2one.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanogchen/rnn-viscoelasticity/e0de2285470d9b08b4aa38b35fb467166a649aab/src/RNN_one2one.pdf -------------------------------------------------------------------------------- /src/RNN_viscoelasticity_3D_2LSTM_1000epochs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanogchen/rnn-viscoelasticity/e0de2285470d9b08b4aa38b35fb467166a649aab/src/RNN_viscoelasticity_3D_2LSTM_1000epochs.pdf -------------------------------------------------------------------------------- /src/myLSTMclass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #! author: GC @ 11/25/2020 customized class for stacked RNN layers 3 | 4 | import numpy as np 5 | import tensorflow as tf 6 | import tensorflow.keras.backend as K 7 | from tensorflow.keras.models import load_model 8 | from tensorflow.keras.layers import LSTM, Dense, TimeDistributed 9 | 10 | def RNN_VE(strain_arr, RNNmodel, states=None): 11 | """ RNN model of VE constitutive law of one sequence 12 | Inputs: strains with the shape (timesteps, n_features) 2-dim inputs 13 | Outputs: the stress prediction values 14 | """ 15 | stress = [] 16 | 17 | # loop around the timesteps 18 | for i in range(strain_arr.shape[0]): 19 | inputs = strain_arr[i,:] 20 | inputs=np.reshape(inputs, (1, 1, inputs.shape[0])) # inputs should be in 3-dim 21 | 22 | outputs, h_state0, c_state0, h_state1, c_state1 = RNNmodel.pred(inputs, states) 23 | istress = K.get_value(outputs) 24 | stress.append(istress) 25 | states = [h_state0, c_state0, h_state1, c_state1] 26 | 27 | return np.asarray(stress) 28 | 29 | class myLSTM(): 30 | def __init__(self, n_hidden, n_features, n_out, model_file): 31 | 32 | self._n_hidden = n_hidden 33 | self._n_features = n_features 34 | self._n_out = n_out 35 | self._model_file = model_file 36 | # self._initial_states = [tf.zeros((1, n_hidden)) for i in range(4)] 37 | 38 | # obtain the weights 39 | best_model = load_model(self._model_file) 40 | weights_list = best_model.weights 41 | # for the LSTM cell 42 | self._kernel_0 = K.get_value(weights_list[0]) 43 | self._rec_kernel_0 = K.get_value(weights_list[1]) 44 | self._bias_rnn_0 = K.get_value(weights_list[2]) 45 | self._kernel_1 = K.get_value(weights_list[3]) 46 | self._rec_kernel_1 = K.get_value(weights_list[4]) 47 | self._bias_rnn_1 = K.get_value(weights_list[5]) 48 | self._kernel_dense = K.get_value(weights_list[6]) 49 | self._bias_dense = K.get_value(weights_list[7]) 50 | 51 | # set up 3 layers 52 | self.lstm_layer1 = LSTM(n_hidden, return_sequences=True, return_state=True) 53 | self.lstm_layer2 = LSTM(n_hidden, return_sequences=True, return_state=True) 54 | self.DenseLayer = TimeDistributed(Dense(n_out, input_shape=(None, 1, self._n_hidden))) 55 | 56 | # set up the model 57 | inputs = tf.keras.Input(shape=(1, self._n_features)) 58 | 59 | # set the first LSTM layer 60 | LSTMout0, h_state0, c_state0 = self.lstm_layer1(inputs) # , initial_state=self._initial_states[0:2]) 61 | 62 | # set the first LSTM layer 63 | LSTMout1, h_state1, c_state1 = self.lstm_layer2(LSTMout0) #, initial_state=self._initial_states[2:]) 64 | 65 | # get the outputs 66 | outputs = self.DenseLayer(LSTMout1) 67 | 68 | # construct the model 69 | self.myRNNet = tf.keras.Model(inputs=inputs, outputs=[outputs, h_state0, c_state0, h_state1, c_state1]) 70 | 71 | # set up the weights 72 | # self.myRNNet.set_weights(weights_list) 73 | self.myRNNet.layers[1].set_weights([self._kernel_0, \ 74 | self._rec_kernel_0, \ 75 | self._bias_rnn_0] ) 76 | 77 | self.myRNNet.layers[2].set_weights([self._kernel_1, \ 78 | self._rec_kernel_1, \ 79 | self._bias_rnn_1] ) 80 | 81 | self.myRNNet.layers[3].set_weights([self._kernel_dense, \ 82 | self._bias_dense ]) 83 | 84 | 85 | def pred(self, input_strains, states=None): 86 | """ 87 | inputs: the (1,1,6) strain input at a single time step 88 | The model has to be inherite from Model so that it can be called directly.!!! 89 | """ 90 | 91 | if states is None: 92 | # set the first LSTM layer 93 | LSTMout0, h_state0, c_state0 = self.lstm_layer1(input_strains) 94 | 95 | # set the first LSTM layer 96 | LSTMout1, h_state1, c_state1 = self.lstm_layer2(LSTMout0) 97 | 98 | # get the outputs 99 | outputs = self.DenseLayer(LSTMout1) 100 | 101 | else: 102 | # set the first LSTM layer 103 | LSTMout0, h_state0, c_state0 = self.lstm_layer1(input_strains, initial_state = states[0:2]) 104 | 105 | # set the first LSTM layer 106 | LSTMout1, h_state1, c_state1 = self.lstm_layer2(LSTMout0, initial_state = states[2:]) 107 | 108 | # get the outputs 109 | outputs = self.DenseLayer(LSTMout1) 110 | 111 | # # construct the model 112 | # self.myRNNet = tf.keras.Model(inputs=inputs, outputs=[outputs, h_state0, c_state0, h_state1, c_state1]) 113 | 114 | return outputs, h_state0, c_state0, h_state1, c_state1 115 | --------------------------------------------------------------------------------