예제 #1
0
def solve_nonlinear_dynamic(component, t0, t_end):
    system, formulation = create_mechanical_system(
        component,
        constant_mass=True,
        constant_damping=True,
        constraint_formulation='boolean')

    solfac = SolverFactory()
    solfac.set_system(system)
    solfac.set_analysis_type('transient')
    solfac.set_integrator('genalpha')
    solfac.set_large_deflection(True)
    solfac.set_nonlinear_solver('newton')
    solfac.set_linear_solver('scipy-sparse')
    solfac.set_acceleration_intializer('zero')
    solfac.set_newton_maxiter(30)
    solfac.set_newton_atol(1e-6)
    solfac.set_newton_rtol(1e-8)
    solfac.set_dt_initial(0.001)

    solver = solfac.create_solver()

    solution_writer = AmfeSolution()

    def write_callback(t, x, dx, ddx):
        u, du, ddu = formulation.recover(x, dx, ddx, t)
        solution_writer.write_timestep(t, u, None, None)

    no_of_dofs = system.dimension
    q0 = np.zeros(no_of_dofs)
    dq0 = q0
    solver.solve(write_callback, t0, q0, dq0, t_end)

    return solution_writer
예제 #2
0
def solve_nonlinear_static(system, formulation, component, load_steps):
    """
    Solves a MechanicalSystem using a nonlinear static method using newton for the nonlinear solver.
    The deformation is divided into an amount of intermediate steps which are defined in the number of load_steps.

    Parameters
    ----------
    system : MechanicalSystem
        Created MechanicalSystem object describing the Structural Component
    formulation : ConstraintFormulation
        A ConstraintFormulation object that can recover the nodal unconstrained displacements of the component
        from the constrained states of the system
    component : StructuralComponent
        StructuralComponent belonging to the system
    load_steps : int
        Number of load steps used for the solution

    Returns
    -------
    solution : amfe.solution.AmfeSolution
        Simple Container for solutions of AMfe simulations
    """
    solfac = SolverFactory()
    solfac.set_system(system)
    solfac.set_analysis_type('static')
    solfac.set_nonlinear_solver('newton')
    solfac.set_linear_solver('scipy-sparse')
    solfac.set_acceleration_intializer('zero')
    solfac.set_newton_maxiter(10)
    solfac.set_newton_atol(1e-8)
    solfac.set_newton_rtol(2e-9)
    solfac.set_dt_initial(1.0 / load_steps)

    solver = solfac.create_solver()

    solution_writer = AmfeSolution()

    no_of_dofs = system.dimension
    q0 = np.zeros(no_of_dofs)
    dq0 = q0
    t0 = 0.0
    t_end = 1.0

    def write_callback(t, x, dx, ddx):
        if isclose(t, t_end):
            u, du, ddu = formulation.recover(x, dx, ddx, t)
            strains, stresses = component.strains_and_stresses(u, du, t)
            solution_writer.write_timestep(t, u, None, None, strains, stresses)

    solver.solve(write_callback, t0, q0, dq0, t_end)

    print('Solution finished')
    return solution_writer
예제 #3
0
def solve_modes(system,
                formulation,
                no_of_modes=10,
                x0=None,
                dx0=None,
                t0=0.0,
                hertz=True):
    """
    Computes the modes of a system, and returns them in a AmfeSolution container

    Parameters
    ----------
    system : MechanicalSystem
        mechanical system
    formulation : ConstraintFormulation
        A ConstraintFormulation object that can recover the nodal unconstrained displacements of the component
        from the constrained states of the system
    no_of_modes : int
        number of modes to compute
    x0 : array_like
        state vector at which the system is linearized
    dx0 : array_like
        derivative of the state vector at which the system is linearized
    t0 : array_like
        time at which the system is linearized
    hertz: bool
        specifies if frequency is measured in Hertz, If False, then the unit 1/s (omega) is used

    Returns
    -------
    modes : AmfeSolution
        AMfeSolution container containing the modes as timesteps. The times are the frequencies of the modes and
        the displacements the corresponding mode shapes.
    """

    if x0 is None:
        x0 = np.zeros(system.dimension)
    if dx0 is None:
        dx0 = np.zeros(system.dimension)

    omega, V = vibration_modes(system.K(x0, dx0, t0), system.M(x0, dx0, t0),
                               no_of_modes)
    modes = AmfeSolution()
    for om, phi in zip(omega, V.T):
        if hertz:
            om = om / (2 * np.pi)
        u_unconstr = formulation.u(phi, 0.0)
        modes.write_timestep(om, u_unconstr)
    return modes
예제 #4
0
    def test_amfe_solution_reader(self):
        self._create_fields()

        amfesolution = AmfeSolution()
        sol = self.fields_desired['Nodefield1']
        for t, q in zip(sol['timesteps'], sol['data'].T):
            amfesolution.write_timestep(t, q)

        mesh = create_amfe_obj()
        meshcomponent = StructuralComponent(mesh)
        # Set a material to get a mapping
        material = KirchhoffMaterial()
        meshcomponent.assign_material(material, 'Tri6', 'S', 'shape')

        postprocessorreader = AmfeSolutionReader(amfesolution, meshcomponent)
예제 #5
0
def solve_linear_static(system, formulation, component):
    """
    Solves a linear, static MechanicalSystem.

    Parameters
    ----------
    system : MechanicalSystem
        MechanicalSystem object describing the equilibrium forces
    formulation : ConstraintFormulation
        A ConstraintFormulation object that can recover the nodal unconstrained displacements of the component
        from the constrained states of the system
    component : StructuralComponent
        Structural Component belonging to the system

    Returns
    -------
    solution : AmfeSolution
        Simple Container for solutions of AMfe simulations
    """
    solfac = SolverFactory()
    solfac.set_system(system)
    solfac.set_analysis_type('static')
    solfac.set_linear_solver('scipy-sparse')

    solver, solver_options = solfac.create_solver()

    solution_writer = AmfeSolution()

    no_of_dofs = system.dimension
    q0 = np.zeros(no_of_dofs)
    dq0 = q0
    ddq0 = dq0

    q = solver.solve(system.K(q0, dq0, 0), system.f_ext(q0, dq0, 0))
    u, du, ddu = formulation.recover(q, dq0, ddq0, 0)
    solution_writer.write_timestep(0, u, None, None)
    logger = logging.getLogger(__name__)
    logger.info(
        'Strains and stresses are currently not supported for linear models. Only nonlinear kinematics are '
        'currently used during their calculation.')

    print('Solution finished')
    return solution_writer
예제 #6
0
def solve_linear_static(component):
    system, formulation = create_mechanical_system(
        component,
        constant_mass=True,
        constant_damping=True,
        constraint_formulation='boolean')

    solver = ScipySparseLinearSolver()

    no_of_dofs = system.dimension
    q0 = np.zeros(no_of_dofs)
    dq0 = q0

    x = solver.solve(system.K(q0, dq0, 0.0), system.f_ext(q0, dq0, 0.0))

    u, _, _ = formulation.recover(x, q0, q0, 0.0)
    solution_writer = AmfeSolution()
    solution_writer.write_timestep(0.0, u, None, None)

    return solution_writer
예제 #7
0
    def setUp(self):
        self.timesteps, self.meshreader, self.fields_desired, \
        self.fields_no_of_nodes, self.fields_no_of_timesteps = create_fields(2)

        amfesolution = AmfeSolution()
        sol = self.fields_desired['Nodefield1']
        strains = copy(self.fields_desired['NodefieldStrains'])
        stresses = copy(self.fields_desired['NodefieldStresses'])
        for i in range(len(sol['timesteps'])):
            t = sol['timesteps'][i]
            q = sol['data'][:, i].T
            strain = strains['data'][:, :, i].T
            stress = stresses['data'][:, :, i].T
            amfesolution.write_timestep(t, q, q, q, strain, stress)

        self.mesh = create_amfe_obj()
        self.meshcomponent = StructuralComponent(self.mesh)
        # Set a material to get a mapping
        material = KirchhoffMaterial()
        self.meshcomponent.assign_material(material, 'Tri6', 'S', 'shape')

        self.postprocessorreader = AmfeSolutionReader(amfesolution,
                                                      self.meshcomponent)
# Solving our system
solution_obj = feti_solver.solve()
"""
We now have our solution, but it's a solution object so we need to 
read it out and store the solution in a way that is readable to us. 
We are going to create ``.hdf5`` and ``.xdmf`` files that contain 
the results.
"""

# Initializing an empty dictionary
solution_writer = dict()

# Save all items from the solution object in the dictionary
for i_prob, local_problem in solution_obj.local_problems.items():
    solution_writer[i_prob] = AmfeSolution()
    q = local_problem.q
    msys = substructured_system.mechanical_systems[i_prob]
    if i_prob in substructured_system.constraint_formulations:
        formulation = substructured_system.constraint_formulations[i_prob]
        u, du, ddu = formulation.recover(q, np.zeros_like(q), np.zeros_like(q),
                                         0)
    else:
        u = q
        du = np.zeros_like(u)
    strains, stresses = structural_composite.components[
        i_prob].strains_and_stresses(u, du, 0)
    solution_writer[i_prob].write_timestep(0, u, None, None, strains, stresses)

# Export the items in files readable in Paraview
for i_comp, comp in structural_composite.components.items():
예제 #9
0
    def test_amfe_solution(self):
        # Only q
        solution = AmfeSolution()
        q1 = np.arange(0, 60, dtype=float)
        q2 = np.arange(10, 70, dtype=float)
        t1 = 0.1
        t2 = 0.5

        solution.write_timestep(t1, q1)
        solution.write_timestep(t2, q2)

        assert_array_equal(solution.q[0], q1)
        assert_array_equal(solution.q[1], q2)
        self.assertEqual(solution.t[0], t1)
        self.assertEqual(solution.t[1], t2)
        self.assertTrue(len(solution.t) == len(solution.q))
        self.assertEqual(len(solution.t), 2)

        # q and dq
        solution = AmfeSolution()
        dq1 = np.arange(20, 80, dtype=float)
        dq2 = np.arange(30, 90, dtype=float)

        solution.write_timestep(t1, q1, dq1)
        solution.write_timestep(t2, q2, dq2)

        assert_array_equal(solution.q[0], q1)
        assert_array_equal(solution.q[1], q2)
        assert_array_equal(solution.dq[0], dq1)
        assert_array_equal(solution.dq[1], dq2)
        self.assertEqual(solution.t[0], t1)
        self.assertEqual(solution.t[1], t2)
        self.assertTrue(len(solution.t) == len(solution.q))
        self.assertTrue(len(solution.t) == len(solution.dq))
        self.assertEqual(len(solution.t), 2)

        # q, dq and ddq
        solution = AmfeSolution()
        ddq1 = np.arange(40, 100, dtype=float)
        ddq2 = np.arange(50, 110, dtype=float)

        solution.write_timestep(t1, q1, dq1, ddq1)
        solution.write_timestep(t2, q2, dq2, ddq2)

        assert_array_equal(solution.q[0], q1)
        assert_array_equal(solution.q[1], q2)
        assert_array_equal(solution.dq[0], dq1)
        assert_array_equal(solution.dq[1], dq2)
        assert_array_equal(solution.ddq[0], ddq1)
        assert_array_equal(solution.ddq[1], ddq2)
        self.assertEqual(solution.t[0], t1)
        self.assertEqual(solution.t[1], t2)
        self.assertTrue(len(solution.t) == len(solution.q))
        self.assertTrue(len(solution.t) == len(solution.dq))
        self.assertTrue(len(solution.t) == len(solution.ddq))
        self.assertEqual(len(solution.t), 2)

        # q and ddq
        solution = AmfeSolution()

        solution.write_timestep(t1, q1, ddq=ddq1)
        solution.write_timestep(t2, q2, ddq=ddq2)

        assert_array_equal(solution.q[0], q1)
        assert_array_equal(solution.q[1], q2)
        assert_array_equal(solution.ddq[0], ddq1)
        assert_array_equal(solution.ddq[1], ddq2)
        self.assertEqual(solution.t[0], t1)
        self.assertEqual(solution.t[1], t2)
        self.assertTrue(len(solution.t) == len(solution.q))
        self.assertTrue(len(solution.t) == len(solution.ddq))
        self.assertEqual(len(solution.t), 2)
        self.assertIsNone(solution.dq[0])
        self.assertIsNone(solution.dq[1])

        # q and strains
        solution = AmfeSolution()
        strains1 = np.random.rand(60, 6)
        strains2 = np.random.rand(60, 6)

        solution.write_timestep(t1, q1, strain=strains1)
        solution.write_timestep(t2, q2, strain=strains2)
        self.assertEqual(solution.t[0], t1)
        self.assertEqual(solution.t[1], t2)
        assert_array_equal(solution.q[0], q1)
        assert_array_equal(solution.q[1], q2)
        assert_array_equal(solution.strain[0], strains1)
        assert_array_equal(solution.strain[1], strains2)
        self.assertIsNone(solution.stress[0])
        self.assertIsNone(solution.stress[1])

        # q, strains and stresses
        solution = AmfeSolution()
        strains1 = np.random.rand(60, 6)
        strains2 = np.random.rand(60, 6)
        stresses1 = np.random.rand(60, 6)
        stresses2 = np.random.rand(60, 6)

        solution.write_timestep(t1, q1, strain=strains1, stress=stresses1)
        solution.write_timestep(t2, q2, strain=strains2, stress=stresses2)
        self.assertEqual(solution.t[0], t1)
        self.assertEqual(solution.t[1], t2)
        assert_array_equal(solution.q[0], q1)
        assert_array_equal(solution.q[1], q2)
        assert_array_equal(solution.strain[0], strains1)
        assert_array_equal(solution.strain[1], strains2)
        assert_array_equal(solution.stress[0], stresses1)
        assert_array_equal(solution.stress[1], stresses2)
        return
예제 #10
0
    def test_pendulum_time_integration(self):
        """
        Test that computes the time integration of the pendulum
        """
        formulation_lagrange = SparseLagrangeMultiplierConstraintFormulation(
            self.cm.no_of_dofs_unconstrained,
            self.M_raw_func,
            self.h_func,
            self.B_func,
            self.p_func,
            self.dh_dq,
            self.dh_ddq,
            g_func=self.g_func)

        formulation_nullspace = NullspaceConstraintFormulation(
            self.cm.no_of_dofs_unconstrained,
            self.M_raw_func,
            self.h_func,
            self.B_func,
            self.p_func,
            self.dh_dq,
            self.dh_ddq,
            g_func=self.g_func,
            a_func=self.a_func)

        sol_lagrange = AmfeSolution()
        sol_nullspace = AmfeSolution()

        formulations = [(formulation_lagrange, sol_lagrange),
                        (formulation_nullspace, sol_nullspace)]
        # Define state: 90deg to the right
        q0 = np.array([0.0, 0.0, self.L, self.L])
        dq0 = np.array([0.0, 0.0, 0.0, 0.0])

        nonlinear_solver = NewtonRaphson()

        for (formulation, sol) in formulations:

            def write_callback(t, x, dx, ddx):
                u = formulation.u(x, t)
                du = formulation.du(x, dx, t)
                ddu = formulation.ddu(x, dx, ddx, t)
                sol.write_timestep(t, u, du, ddu)

            integrator = GeneralizedAlpha(formulation.M,
                                          formulation.f_int,
                                          formulation.f_ext,
                                          formulation.K,
                                          formulation.D,
                                          alpha_m=0.0)
            integrator.dt = 0.025
            integrator.nonlinear_solver_func = nonlinear_solver.solve
            integrator.nonlinear_solver_options = {'rtol': 1e-7, 'atol': 1e-6}

            # Initialize first timestep
            t = 0.0
            t_end = 0.5
            x = np.zeros(formulation.dimension)
            dx = np.zeros(formulation.dimension)
            ddx = np.zeros(formulation.dimension)
            x[:4] = q0
            dx[:4] = dq0

            # Call write timestep for initial conditions
            write_callback(t, x, dx, ddx)

            # Run Loop
            while t < t_end:
                t, x, dx, ddx = integrator.step(t, x, dx, ddx)
                write_callback(t, x, dx, ddx)

        def plot_pendulum_path(u_plot):
            plt.scatter(self.X[2] + [u[2] for u in u_plot],
                        self.X[3] + [u[3] for u in u_plot])
            plt.title(
                'Pendulum-test: Positional curve of rigid pendulum under gravitation'
            )
            return

        # UNCOMMENT THESE LINES IF YOU LIKE TO SEE A TRAJECTORY (THIS CAN NOT BE DONE FOR GITLAB-RUNNER
        # plot_pendulum_path(sol_lagrange.q)
        # plot_pendulum_path(sol_nullspace.q)
        # plt.show()

        # test if nullspace formulation is almost equal to lagrangian
        # and test if constraint is not violated
        for q_lagrange, q_nullspace in zip(sol_lagrange.q, sol_nullspace.q):
            assert_allclose(q_nullspace, q_lagrange, atol=1e-1)
            x_lagrange = self.X.reshape(-1) + q_lagrange
            x_nullspace = self.X.reshape(-1) + q_nullspace
            assert_allclose(np.array(
                [np.linalg.norm(x_lagrange[2:] - x_lagrange[:2])]),
                            np.array([self.L]),
                            atol=1e-3)
            assert_allclose(np.array(
                [np.linalg.norm(x_nullspace[2:] - x_nullspace[:2])]),
                            np.array([self.L]),
                            atol=1e-1)
예제 #11
0
    def test_pendulum_time_integration(self):
        """
        Test that computes the time integration of the pendulum
        """
        formulation_lagrange = SparseLagrangeMultiplierConstraintFormulation(self.cm.no_of_dofs_unconstrained,
                                                                             self.M_raw_func, self.h_func, self.B_func,
                                                                             self.p_func, self.dh_dq, self.dh_ddq,
                                                                             g_func=self.g_func)

        formulation_nullspace = NullspaceConstraintFormulation(self.cm.no_of_dofs_unconstrained, self.M_raw_func,
                                                               self.h_func, self.B_func, self.p_func,
                                                               self.dh_dq, self.dh_ddq,
                                                               g_func=self.g_func, a_func=self.a_func)

        sol_lagrange = AmfeSolution()
        sol_nullspace = AmfeSolution()
        phi_analytical = []

        formulations = [(formulation_lagrange, sol_lagrange), (formulation_nullspace, sol_nullspace)]
        # Define state: 90deg to the right
        q0 = np.array([0.0, 0.0, self.L, self.L])
        dq0 = np.array([0.0, 0.0, 0.0, 0.0])

        nonlinear_solver = NewtonRaphson()

        for (formulation, sol) in formulations:

            def write_callback(t, x, dx, ddx):
                u = formulation.u(x, t)
                du = formulation.du(x, dx, t)
                ddu = formulation.ddu(x, dx, ddx, t)
                sol.write_timestep(t, u, du, ddu)

            integrator = GeneralizedAlpha(formulation.M, formulation.f_int, formulation.f_ext, formulation.K,
                                          formulation.D,
                                          alpha_m=0.0)
            integrator.dt = 0.025
            integration_stepper = NonlinearIntegrationStepper(integrator)
            integration_stepper.nonlinear_solver_func = nonlinear_solver.solve
            integration_stepper.nonlinear_solver_options = {'rtol': 1e-7, 'atol': 1e-6}

            # Initialize first timestep
            t = 0.0
            t_end = 0.5
            x = np.zeros(formulation.dimension)
            dx = np.zeros(formulation.dimension)
            ddx = np.zeros(formulation.dimension)
            x[:4] = q0
            dx[:4] = dq0

            # Call write timestep for initial conditions
            write_callback(t, x, dx, ddx)

            i = 0
            # Run Loop
            while t < t_end:
                phi_analytical.append(np.pi / 2 * np.cos(np.sqrt(self.g / self.L) * t))
                t, x, dx, ddx = integration_stepper.step(t, x, dx, ddx)
                write_callback(t, x, dx, ddx)
                i += 1

            phi_analytical.append(np.pi / 2 * np.cos(np.sqrt(self.g / self.L) * t))

        def plot_pendulum_path(u_plot, label_name):
            return plt.scatter(self.X[2]+[u[2] for u in u_plot], self.X[3]+[u[3] for u in u_plot], label=label_name)


        plt.title('Pendulum-test: Positional curve of rigid pendulum under gravitation')
        lagrange = plot_pendulum_path(sol_lagrange.q, 'Lagrange')
        nullspace = plot_pendulum_path(sol_nullspace.q, 'Nullspace')
        # ANALYTICAL SOLUTION FOR SMALL ANGLES
        #analytical = plt.scatter([self.L*np.sin(phi) for phi in phi_analytical], [-self.L*np.cos(phi) for phi in phi_analytical], label='Analytical')
        axes = plt.gca()
        axes.set_xlim([-2.1, 2.1])
        axes.set_ylim([-2.1, 2.1])
        plt.legend(handles=[lagrange, nullspace])#, analytical])
        # UNCOMMENT NEXT LINE IF YOU LIKE TO SEE A TRAJECTORY (THIS CAN NOT BE DONE FOR GITLAB-RUNNER)
        # plt.show()

        # test if nullspace formulation is almost equal to lagrangian
        # and test if constraint is not violated
        for q_lagrange, q_nullspace in zip(sol_lagrange.q, sol_nullspace.q):
            assert_allclose(q_nullspace, q_lagrange, atol=1e-1)
            x_lagrange = self.X.reshape(-1) + q_lagrange
            x_nullspace = self.X.reshape(-1) + q_nullspace
            assert_allclose(np.array([np.linalg.norm(x_lagrange[2:] - x_lagrange[:2])]), np.array([self.L]), atol=1e-3)
            assert_allclose(np.array([np.linalg.norm(x_nullspace[2:] - x_nullspace[:2])]), np.array([self.L]), atol=1e-1)
예제 #12
0
    constraint_formulation='boolean')

solfac = SolverFactory()

solfac.set_system(system)
solfac.set_analysis_type('static')
solfac.set_dt_initial(0.05)
solfac.set_analysis_type('zero')
solfac.set_linear_solver('pardiso')
solfac.set_newton_verbose(True)
solfac.set_nonlinear_solver('newton')
solfac.set_newton_atol(1e-5)
solfac.set_newton_rtol(1e-7)
solver = solfac.create_solver()

solution = AmfeSolution()


def write_callback(t, x, dx, ddx):
    u, du, ddu = formulation.recover(x, dx, ddx, t)
    solution.write_timestep(t, u, du, ddu)


x0 = np.zeros(system.dimension)
dx0 = x0.copy()
t0 = 0.0
t_end = 1.0

solver.solve(write_callback, t0, x0, dx0, t_end)

write_results_to_paraview(solution, my_component, output_file)
예제 #13
0
solfac.set_linear_solver('scipy-sparse')
solfac.set_acceleration_intializer('zero')
solfac.set_newton_maxiter(20)
solfac.set_newton_atol(1e-8)
solfac.set_newton_rtol(1e-9)
solfac.set_dt_initial(0.00001)
solfac._alpha_f = 0.25
solfac._alpha_m = 0.25
solfac._gamma = 0.75
solfac._beta = 0.390625


residuals = list()

mysolver = solfac.create_solver()
writer = AmfeSolution()


def write_callback(t, x, dx, ddx):
    u, du, ddu = formulation.recover(x, dx, ddx, t)
    writer.write_timestep(t, u, du, ddu)


t0 = 0.0
t_end = 0.15

no_of_dofs = system.dimension
q0 = np.zeros(no_of_dofs)
dq0 = q0.copy()
q0[:len(q0_raw)] = q0_raw
dq0[:len(dq0_raw)] = dq0_raw
예제 #14
0
def solve_nonlinear_dynamic(system,
                            formulation,
                            component,
                            t0,
                            t_end,
                            dt,
                            write_each=1):
    """
    Solves a system

    Parameters
    ----------
    system : MechanicalSystem
        Created MechanicalSystem object describing the Structural Component
    formulation : ConstraintFormulation
        A ConstraintFormulation object that can recover the nodal unconstrained displacements of the component
        from the constrained states of the system
    component : StructuralComponent
        StructuralComponent belonging to the system
    t0 : float
        initial time
    t_end : float
        final time
    dt : float
        increment between time steps
    write_each : int
        Specifies that the solver writes every n'th solution (eg. type 2 to write every second timestep)

    Returns
    -------
    solution : amfe.solution.AmfeSolution
        Simple Container for solutions of AMfe simulations
    """
    solfac = SolverFactory()
    solfac.set_system(system)
    solfac.set_analysis_type('transient')
    solfac.set_integrator('genalpha')
    solfac.set_nonlinear_solver('newton')
    solfac.set_linear_solver('scipy-sparse')
    solfac.set_acceleration_intializer('zero')
    solfac.set_newton_maxiter(10)
    solfac.set_newton_atol(1e-8)
    solfac.set_newton_rtol(2e-11)
    solfac.set_dt_initial(dt)

    solver = solfac.create_solver()

    solution_writer = AmfeSolution()

    def write_callback(t, x, dx, ddx):
        cur_ts = int((t - t0) // dt)
        if abs(cur_ts % write_each) <= 1e-7:
            u, du, ddu = formulation.recover(x, dx, ddx, t)
            strains, stresses = component.strains_and_stresses(u, du, t)
            solution_writer.write_timestep(t, u, du, ddu, strains, stresses)

    no_of_dofs = system.dimension
    q0 = np.zeros(no_of_dofs)
    dq0 = q0
    solver.solve(write_callback, t0, q0, dq0, t_end)

    print('Solution finished')
    return solution_writer
예제 #15
0
def solve_linear_dynamic(system,
                         formulation,
                         component,
                         t0,
                         t_end,
                         dt,
                         write_each=1):
    """
    Solves a linear, dynamic MechanicalSystem from t0 to t_end with dt as intermediate steps.

    Parameters
    ----------
    system : MechanicalSystem
        MechanicalSystem object describing the equations of motion
    formulation : ConstraintFormulation
        A ConstraintFormulation object that can recover the nodal unconstrained displacements of the component
        from the constrained states of the system
    component : StructuralComponent
        StructuralComponent belonging to the system
    t0 : float
        initial time
    t_end : float
        final time
    dt : float
        increment between time steps
    write_each : int
        Specifies that the solver writes every n'th solution (eg. type 2 to write every second timestep)

    Returns
    -------
    solution : amfe.solution.AmfeSolution
        AmfeSolution container that contains the solution
    """
    solfac = SolverFactory()
    solfac.set_system(system)
    solfac.set_analysis_type('transient')
    solfac.set_linear_solver('scipy-sparse')
    solfac.set_integrator('newmarkbeta')
    solfac.set_acceleration_intializer('zero')
    solfac.set_dt_initial(dt)

    solver = solfac.create_solver()

    no_of_dofs = system.dimension
    q0 = np.zeros(no_of_dofs)
    dq0 = q0

    solution_writer = AmfeSolution()

    def write_callback(t, x, dx, ddx):
        cur_ts = int((t - t0) // dt)
        if abs(cur_ts % write_each) <= 1e-7:
            u, du, ddu = formulation.recover(x, dx, ddx, t)
            solution_writer.write_timestep(t, u, du, ddu)

    solver.solve(write_callback, t0, q0, dq0, t_end)

    logger = logging.getLogger(__name__)
    logger.info(
        'Strains and stresses are currently not supported for linear models. Only nonlinear kinematics are '
        'currently used during their calculation.')

    print('Solution finished')
    return solution_writer