Applications, Examples and Libraries

Share your work here

Maple Transactions has just published the Autumn 2024 issue at mapletransactions.org

From the header:

This Autumn Issue contains a "Puzzles" section, with some recherché questions, which we hope you will find to be fun to think about.  The Borwein integral (not the Borwein integral of XKCD fame, another one) set out in that section is, so far as we know, open: we "know" the value of the integral because how could the identity be true for thousands of digits but yet not be really true? Even if there is no proof.  But, Jon and Peter Borwein had this wonderful paper on Strange Series and High Precision Fraud showing examples of just that kind of trickery.  So, we don't know.  Maybe you will be the one to prove it! (Or prove it false.)

We also have some historical papers (one by a student, discussing the work of his great grandfather), and another paper describing what I think is a fun use of Maple not only to compute integrals (and to compute them very rapidly) but which actually required us to make an improvement to a well-known tool in asymptotic evaluation of integrals, namely Watson's Lemma, just to explain why Maple is so successful here.

Finally, we have an important paper on rational interpolation, which tells you how to deal well with interpolation points that are not so well distributed.

Enjoy the issue, and keep your contributions coming.

With the 2024 Maple Conference coming up this week, I imagine one of two of you have noticed something missing. We chose not to have a Conference Art Gallery this year, because we have been working to launch new section of MaplePrimes:  The MaplePrimes Art Gallery. This new section of MaplePrimes is designed for showing off your Maple related images, in a gallery format that puts the images up front, like Instagram but for Math.

To get the ball rolling on the gallery, I have populated it with many of the works from past years' Maple Art Galleries, so you can now browse them all in one place, and maybe give "Thumbs Ups" to art pieces that you felt should have won the coveted "People's Choice Award".

Once you are inspired by past entries, we welcome you to submit your new artwork!  Just like the conference galleries, we are looking for all sorts of mathematical art ranging from computer graphics and animations, to photos of needlework, geometrical sculptures, or almost anything!  Art Gallery posts are very similar to regular MaplePrimes posts except that you are asked to supply an Image File and a Caption that will displayed on the main Gallery Page, the post itself can include a longer description, Maple commands, additional images, and whatever else you like.  See for example this Art Gallery post describing Paul DeMarco's sculpture from the 2021 Maple Conference Gallery - it includes an embedded worksheet as well as additional images.

I can't wait to see what new works of art our MaplePrimes community creates!

 


This is an answer to the last question ASHAN recently asked.
As this answer goes beyond the simple example supplied by ASHAN in that it extends the possibilities of Statistics:-ColumnGraph, I thought it would be appropriate to share it with the entire community of Maple users.

Possible improvements:

  • add controls for parameter types
  • add consistency controls (numer of colors = number of data rows for instance)
  • add some custom parameters
  • improve legend position
     

restart

CustomColumnGraph := proc(
                       data
                       , BarColors
                       , GroupTitles
                       , BarWidth         
                       , GroupOffset      
                       , LegendBarHeight
                       , VerticalShiftFactor
                       , BarFont
                       , GroupFont
                       , LegendFont
                       , BarTitleFormat
                     )



  local Ni, Nj, W, DX, LH, LW, SF, L, DL:

  local SingleBar := (w, h, c) -> rectangle([0, 0], [w, h], color=c):
  local BarGraph, Legends:

  uses plots, plottools:

  Ni := numelems(data[..,1]):
  Nj := numelems(data[1]):
  W  := BarWidth:
  DX := GroupOffset:
  LH := LegendBarHeight:
  SF := VerticalShiftFactor;
  L  := DX*(Ni-1) + W*(Nj-1) + DX/2 + DX/4:
  LW := L / Ni / Nj / 2;                          # LegendBarWidth  
  DL := solve(dl*(Nj+1) + Nj*(3*LW) = L, dl);



  BarGraph := display(
                seq(
                  seq(
                    translate(SingleBar(W, data[i, j], BarColors[j]), DX/4 + DX*(i-1) + W*(j-1), 0)
                    , i=1..Ni
                  )
                  , j=1..Nj
                )
                , axis[1] = [gridlines = [], tickmarks = []]
                , axis[2] = [gridlines = [11, linestyle = dot, thickness = 0, color = "LimeGreen"]]
              ):

  Legends := display(
               seq(
                 translate(SingleBar(LW, LH, BarColors[j]), DL/2 + LW + (3*LW+DL)*(j-1), min(data)*(2*SF-1))
                 , j=1..Nj
               )
               ,
               seq(
                 translate(
                   textplot([0, LH/2, GroupTitles[j]], align=right, font = LegendFont)
                   , DL/2 + 2*LW + (3*LW+DL)*(j-1), min(data)*1.4)
                   , j=1..Nj
               )
             ):

  display(
    BarGraph  
    , Legends

    #------------------------------- X base line
    , plot(0, x=0..DX*(Ni-1)+W*(Nj-1)+DX/2 + DX/4)
 
    #------------------------------- Left bar group boundaries
    ,
    seq(
      line(
        [DX/4 + DX*(i-1) - W/2, min(data)*SF],
        [DX/4 + DX*(i-1) - W/2, max(data)*SF]
        , color="LightGray"
      )
      , i=1..Ni
    )


    #------------------------------- Right bar group boundaries
    ,
    seq(
      line(
        [DX/4 + DX*(i-1) + W*Nj + W/2, min(data)*SF],
        [DX/4 + DX*(i-1) + W*Nj + W/2, max(data)*SF]
        , color="LightGray"
      )
      , i=1..Ni
    )
  
    #------------------------------- Top bar group boundaries
    ,
    seq(
      line(
        [DX/4 + DX*(i-1) - W/2, max(data)*SF],
        [DX/4 + DX*(i-1) + W*Nj + W/2, max(data)*SF]
        , color="LightGray"
      )
      , i=1..Ni
    )
 
    #------------------------------- Bar titles
    ,
    seq(
      seq(
        textplot(
          # [DX/4 + DX*(i-1) + W*(j-1) +W/2, data[i, j], evalf[3](data[i, j])]
          [DX/4 + DX*(i-1) + W*(j-1) +W/2, data[i, j], sprintf(BarTitleFormat, data[i, j])]
          , font=BarFont
          , align=`if`(data[i, j] > 0, above, below)
        )
        , i=1..Ni
      )
      , j=1..Nj
    )
  
    #------------------------------- Bar group titles
    ,
    seq(
      textplot(
        [DX/4 + DX*(i-1) + W*(Nj/2), max(data)*SF, cat("B", i)]
        , font=GroupFont
        , align=above
      )
      , i=1..Ni
    )
  
    , labels=["", ""]
    , size=[800, 400]
    , view=[0..DX*(Ni-1) + W*(Nj-1) + DX/2 + DX/4, default]
  );
end proc:

 

Data from  AHSAN

 

A := [0.1, 0.5, 0.9]:
B := [0.5, 2.5, 4.5]:


Nu_A := [-0.013697, 0.002005, 0.017707, -0.013697, 0.002005, 0.017707, -0.013697, 0.002005, 0.017707]:
Nu_B := [0.010827, 0.011741, 0.012655, 0.013967, 0.014881, 0.015795, 0.017107, 0.018021, 0.018935]:


i:=4:
data := Matrix([[Nu_A[i], Nu_B[i]], [Nu_A[i + 1], Nu_B[i + 1]], [Nu_A[i + 2], Nu_B[i + 2]]]):
 

 

Column Graph

 

Ni, Nj := LinearAlgebra:-Dimensions(data):

CustomColumnGraph(
                   data                                        # data
                   , ["Salmon", "LightGreen"]                  # BarColors
                   , ["Sensitivity to A", "Sensitivity to B"]  # GroupTitles
                   , 1/(numelems(data[1])+2)                   # BarWidth  
                   , 1                                         # GroupOffset  
                   , max(abs~(data))/10                        # LegendBarHeight
                   , 1.2                                       # VerticalShiftFactor
                   , [Tahoma, bold, 10]                        # BarFont
                   , [Tahoma, bold, 14]                        # GroupFont
                   , [Tahoma, bold, 12]                        # LegendFont
                   , "%1.5f"                                   # BarTitleFormat
                 )

 

 

Column Graph of an extended set of data

 

 

ExtentedData := < data | Statistics:-Mean(data^+)^+ >:
ExtentedData := < ExtentedData, Statistics:-Mean(ExtentedData) >:

interface(displayprecision=6):
data, ExtentedData;

Ni, Nj := LinearAlgebra:-Dimensions(ExtentedData):


CustomColumnGraph(
                   ExtentedData                                  
                   , ["Salmon", "LightGreen", "Moccasin"]                 
                   , ["Sensitivity to A", "Sensitivity to B", "Mean Sensitivity to A and B"]
                   , 1/(numelems(data[1])+2)                   # BarWidth  
                   , 1                                         # GroupOffset  
                   , max(abs~(data))/10                        # LegendBarHeight
                   , 1.2                                       # VerticalShiftFactor
                   , [Tahoma, 10]                              # BarFont
                   , [Tahoma, bold, 14]                        # GroupFont
                   , [Tahoma, 12]                              # LegendFont
                   , "%1.3f"                                   # BarTitleFormat
                 )

Matrix(3, 2, {(1, 1) = -0.13697e-1, (1, 2) = 0.13967e-1, (2, 1) = 0.2005e-2, (2, 2) = 0.14881e-1, (3, 1) = 0.17707e-1, (3, 2) = 0.15795e-1}), Matrix(4, 3, {(1, 1) = -0.13697e-1, (1, 2) = 0.13967e-1, (1, 3) = HFloat(1.349999999999997e-4), (2, 1) = 0.2005e-2, (2, 2) = 0.14881e-1, (2, 3) = HFloat(0.008442999999999999), (3, 1) = 0.17707e-1, (3, 2) = 0.15795e-1, (3, 3) = HFloat(0.016751000000000002), (4, 1) = HFloat(0.002005), (4, 2) = HFloat(0.014881), (4, 3) = HFloat(0.008443)})

 

 

 

 


 

Download CustomColumnGraph.mw

 

This post is about the visualization of a gyroscopic phenomenon of a rotating body. MapleSim models and a description for those who do not have MapleSim are provided for their own analysis. Implementation with other tools like Maple might give further insight into the phenomenon.

With appropriate initial conditions, a ball thrown into a tube can pop out of the tube. This can be reproduced with a MapleSim model

Throwing_a_ball_into_a_tube_A.msim

To hit a perfect shot without trial and error, time reversal was applied for the model (reversed calculation results of a ball exiting the tube are used as initial conditions for the shot). This worked straight away and shows that this model is sufficiently conservative.

This phenomenon has recently attracted attention on YouTube. For example, Steve Mold demonstrates the effect and provides an intuitive explanation which he considers incomplete because the resulting vertical oscillation of the ball does not match theory and his experiments. He suspects that the assumption of a constant axis of rotation of the ball is responsible for this discrepancy.

However, he cannot demonstrate a change of the axis of rotation. In general, the visualization of the rotation axis of a ball is difficult to achieve in an experiment. On the contrary, visualization is much easier in a simulation experiment with this model:

Throwing_a_ball_into_a_tube_B.msim

The following can be observed for a trajectroy that does not exit the tube:

At the apex (the top) of the trajectory, the vector of rotation (red bold in the following images) points downwards and is essentially parallel to the axis of the cylinder. The graph to the left shows the vertical (in green) position and one horizontal position (in red). The model applies gravity in negative y direction.

Ein Bild, das Text, Diagramm, Screenshot, Reihe enthält.

Automatisch generierte Beschreibung 

On the way down, the axis of rotation points away from the direction of travel (the ball orbits counterclockwise in the top view).

Ein Bild, das Text, Diagramm, Screenshot, Reihe enthält.

Automatisch generierte Beschreibung

At the bottom, the vector of rotation points towards the axis of the cylinder.

Ein Bild, das Text, Diagramm, Screenshot, Reihe enthält.

Automatisch generierte Beschreibung

On the way up, the axis of rotation points in the direction of travel.

Ein Bild, das Text, Diagramm, Screenshot, Reihe enthält.

Automatisch generierte Beschreibung

These observations confirm that the assumption of a constant axis of rotation is too simplified. Effectively the ball performs a precession movement know from gyroscopes. More specifically, the precession movement of the rotation axis rotates in the opposite direction of the rotation of the ball.

However, the knowledge and the visualization of this precession movement do not provide more insight for a better intuitive explanation of the effect. As the ball acts like a gyroscope, a second attempt is to visualize forces that perturb the motion of the ball. Besides gravity, there are contact forces exerted by the tube. The normal force at the contact as well as the gravitational force cannot generate a perturbing momentum since they point to the center of the ball. Only frictional forces at the contact can cause a perturbing momentum.

Contrary to the visualization of the axis of rotation, visualization of contact forces is not straight forward in MapleSim, because neither the contact point nor the contact forces are directly provided by components of the MapleSim library. Only for a single contact point, a work-around is possible by measuring the reactive forces on the tube and then displaying these forces in a moving reference frame at the contact point. The location and the orientation of this frame are calculated with built-in mathematical components. To illustrate the additional effort, the image below highlights in yellow the components only needed for the visualization of the above images, all other components were required to visualize the contact forces and frictional moments.
Ein Bild, das Text, Diagramm, Plan, parallel enthält.

Automatisch generierte Beschreibung
Throwing_a_ball_into_a_tube_C3.msim
It required many attempts to get to a working model. Several kinematic models for a rotating reference frame at the contact point failed. Finally, mathematical operations on kinematic signals (measured by sensors) and motion drivers were successful.  

In the following, the model is used to visualize the right-hand rule for the following vectors:

  • in green the disturbing frictional moment
  • in red (now with a double headed arrow) the angular velocity (for a sphere it points in the same direction as the vector of the angular momentum and the axis of rotation)
  • in pink the vector of the angular velocity of the precession movement

At the top, the vector of precession indicates that the axis of rotation is diverted away from the direction of travel (i.e. pointing backwards). This is in line with the above image of the ball “on the way down”.

Ein Bild, das Screenshot, Text, Diagramm, Reihe enthält.

Automatisch generierte Beschreibung

At the bottom, the vector of precession indicates also that the axis of rotation is diverted away from the direction of travel. This however cannot be seen in the above image of the ball “on the way up”. This discrepancy is an indication that the vector of angular velocity of the precession movement might not sufficiently predict the future orientation of the axis of rotation.

Overall, there is little symmetry in the two extreme positions at the top and at the bottom. A bending of the trajectory downwards (pitching down) at the top indicated by the vector of precession, cannot be seen at the bottom: The vector of precession does not indicate a bending of the trajectory in an upward direction.

It turns out that the right-hand rule does not provide the hoped-for better explanation either. However, the model was not a complete waste of time since it provided two unexpected and very counterintuitive observations:

  • At the bottom, the speed of the balls center is the lowest. For an object descending in a gravitational field, one would expect a gain in speed. A closer look at the graph of the angular velocity (lower graph) reveals that the ball is spinning at the highest rate at the bottom. This means that potential and kinetic energy at the top are converted to rotational energy at the bottom.
  • Although the ball slows down (and speeds up in angular velocity) while descending there is no frictional force component in circumferential direction. Seen from above, the ball orbits at constant velocity. Only a vertical frictional force component acts all the time. Frictional forces in circumferential direction slowing down the ball can only be seen at the beginning of the simulation when the ball slips on the tube up to the moment when it rolls without slippage.

Overall, the closer one looks, the less intuitive it gets. What makes this phenomenon so difficult to understand is the constantly changing constraint of the ball. At each time increment the location and orientation of the contact changes with respect to the direction of the (instantaneous) direction of precession. This makes the phenomenon so obscure. It might be easier to find an “intuitive” explanation for the tennis racket paradox (or intermediate axis theorem) where no external forces act.

Even with a physics background and the right-hand rule of precession at hand, it requires allot of imagination to predict the movement of the ball. This is, in my opinion, not intuitive at all for most people. After all, the premotor cortex of the human brain seems to have constant difficulties to learn precession – for sure precession prediction is not hardwired. If it was, the paradox wasn’t so perplexing, and we could imagine/predict what the golf ball does next.

In summary, this simulation experiment revealed details not known before (at least to me) about the phenomenon. The experiment did not provide more insight for a better intuitive explanation but on the contrary raised more questions. It is another case of “knowing more, but not getting smarter”.

At the very least, the simulations also show the benefits of carrying out virtual experiments under various conditions that are difficult or even impossible in an experiment. In any case, such experiments are of educational value  - not only in classical physics.

 

Comments on the product:

It was possible to verify results of MapleSim: The model reproduces the magic numbers sqrt(7/2) and sqrt(5/2) for the ratios of circular rotation and vertical oscillation frequencies for a full and a hollow sphere respectively. See the first model.

The (laborious) work-around presented here cannot be applied to most real-world contact problems. Visualization of the contact point, contact forces and contact slippage are therefore a desirable extension to MapleSim’s contact capabilities. I do not think that this is provided by other tools.

A surface pattern for the ball would have been helpful to better visualize the rotation of the ball.

A moving observer view (in this case an observer in the reference frame of the contact) could facilitate observation.

Further viewing:

  • The physical engine of Blender was used in a video to reproduce the phenomenon qualitatively.
  • There is an ”improved” intuitive explanation of Steve Mold’s explanation which uses frictional forces and provides physical background. It is not clear to me which part of the visualization is animated and which is physically simulated. At least some sequences do not make sense: The vector of the external frictional moment on the ball suddenly changes direction. The “improved” intuitive explanation also states that the rotational axis leans constantly toward the contact point. I do not see this in my simulation (the contact point is indicated with a red dot in the images above). Also, the precession vectors in my simulation did not reveal an intuitive explanation for a reduction in vertical oscillation frequency.

Further work:

  • Is the vertical oscillation truly sinusoidal as the horizontals are?
  • Is the point of contact always in the northern hemisphere of the ball? More general: In one hemisphere?
  • In a simulation without gravity: Does the vector of precession better predict the trajectory?
  • ...
     

Here is a procedure I wrote to apply a greek prefix to a value so that the coefficient lies between 1 and 1000.

 

applyGreekPrefix := proc(x)
	description
		"Accepts a number, and if it has units, a Greek prefix is added so that the coefficient is between 1 and 1000",
		"Values without units or a unit of muliple units are returned as-is"
	;
	local prefixes, powers, value, unit, exponent, new_value, idx, prefix, strUnit, new_unit, i, SIx, returnval;
	
	if Units:-Split(x)[2] = 1 or numelems(indets(op(2, x), 'name')) > 1 then	
		# Value has no units or consists of multiple units
		returnval := x;
	else
		# Define the SI prefixes and their corresponding powers of 10
		prefixes := ["q", "r", "y", "z", "a", "f", "p", "n", "μ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"];
		powers := [seq(i, i = -30 .. 30, 3)];
		
		# Convert to SI unit w/o prefix
		SIx := convert(x, 'system', 'SI');		
		# Separate the value and the unit
		value := evalf(op(1, SIx));
		unit := op(2, SIx);
		strUnit := convert(unit, string);  # Convert the unit to a string representation
		
		# Calculate the exponent of 10 for the value
		exponent := floor(log10(abs(value)));
		
		# Find the closest power of 10 that makes the coefficient between 1 and 1000
		idx := 0;
		for i from 1 to nops(powers) do
		   if exponent >= powers[i] then
		       idx := i;
		   end if;
		end do;
		
		# Adjust the value based on the selected prefix
		new_value := value / 10^powers[idx];
		prefix := prefixes[idx];
		# Construct the new unit using Units:-Unit if a prefix is needed
		if prefix = "" then
		   new_unit := unit; # No prefix needed, use the original unit
		else
		   new_unit := parse(StringTools:-Substitute(strUnit, "Units:-Unit(", cat("Units:-Unit(", prefix))); # Construct a new unit with the prefix
		end if;
		
		# Return the adjusted value with the new unit
		returnval := new_value * new_unit;
	end if;	
	return returnval;
end proc:
list_tests:=[0.0001*Unit('kV'), 10000*Unit('V'), 10*Unit('V'/'us'), 12334];
for test in list_tests do
	print (test, "becomes", applyGreekPrefix(test));
end do;

 

The complete Maple Conference 2024 program is now available online. You can view it HERE.
Thank you to all those who voted for the "Audience Choice" sessions. The winning topics are listed in the program.

Registration is still open and free of charge.  

We hope to see you there!

Just finished an exciting lecture for undergraduate students on Euler methods for solving ordinary differential equations (ODEs)! 📝 We explored the Euler method and the Improved Euler method (a.k.a. Heun's method) and discussed how these fundamental techniques work for approximating solutions to ODEs.

To make things practical and hands-on, I demonstrated how to implement both methods using Maple—a fantastic tool for experimenting with numerical methods. Seeing these concepts come to life with visualizations helps understand the pros and cons of each method.

The Euler method is the simplest numerical approach, where we approximate the solution by stepping along the slope given by the ODE. But there's a catch: using a large step size can lead to large errors that accumulate quickly, causing significant deviation from the real solution.

Plot Results:

  • With a larger step size (h=0.5h = 0.5h=0.5), the solution tends to drift away significantly from the actual curve.
  • Reducing the step size improves accuracy, but it also means more steps and more computation.

Next, we discussed the Improved Euler method, which is like Euler's smarter sibling. Instead of blindly following the initial slope, it:

  1. Estimates the slope at the start.
  2. Uses that slope to predict an intermediate value.
  3. Then, it takes another slope at the intermediate point.
  4. Averages these two slopes for a better approximation.

This technique makes a big difference in accuracy and stability, especially with larger step sizes.

Plot Results:

  • Using the Improved Euler method, we found that even with a larger step size, the solution is smoother and closer to the true path.
  • The average slope helps mitigate the inaccuracies that arise from only using the beginning point's derivative, effectively reducing the local error.
  • The standard Euler method can produce solutions that oscillate or diverge, especially for larger step sizes.
  • The Improved Euler method follows the actual trend of the solution more faithfully, even with fewer steps. This makes it a more efficient choice for balancing computational effort and accuracy.
  • The Euler method is great for its simplicity but often requires very small step sizes to be accurate, leading to more computational effort.
  • The Improved Euler method—which we implemented and visualized on Maple—proved to be more reliable and accurate, especially for larger step sizes.

It was amazing to see the students engage with these foundational methods, and implementing them on Maple brought a deeper understanding of numerical analysis and the challenges of solving differential equations.


 


restart

with(plots)

with(DEtools)

ODE1 := diff(y(x), x) = -2*x*y(x)/(x^2+1)

diff(y(x), x) = -2*x*y(x)/(x^2+1)

(1)

NULL

We calculate the general solution to the ODE

NULL

dsolve(ODE1, y(x))

y(x) = c__1/(x^2+1)

(2)

NULL

Now let's solve the problem for the following two inital conditions

y(0) = 2 and y(0) = 1/2

dsolve({ODE1, y(0) = 2}, y(x))

y(x) = 2/(x^2+1)

(3)

dsolve({ODE1, y(0) = 1/2}, y(x))

y(x) = 1/(2*x^2+2)

(4)

Then, we are going to plot the solutions to the IVP's together with the slope field corresponding to the ODE.

 

NULLdfieldplot(ODE1, [y(x)], x = -5 .. 5, y = -5 .. 5, color = blue, scaling = constrained, axes = boxed)

 

 

DEplot(ODE1, y(x), x = -5 .. 5, y = -5 .. 5, [[y(0) = 2], [y(0) = 4]], linecolor = red, color = blue, scaling = constrained, axes = boxed)

 

Problem 2 (EULER METHOD)

NULL

NULL

ODE2 := diff(y(x), x) = sin(x*y(x))

diff(y(x), x) = sin(x*y(x))

(5)

 

 

dsolve(ODE2, y(x))

NULL

Maple returned no output! That means Maple is unable to solve the equation.

NULL

If you are curious what steps Maple went through to  find a solution before failing
to do so, you can ask to see the steps using the command "infolevel". The levels
of information that you can request range from 0 to 5.

 

````

dsolve(ODE2, y(x))

soln := dsolve({ODE2, y(0) = 3}, y(x), numeric)

proc (x_rkf45) local _res, _dat, _vars, _solnproc, _xout, _ndsol, _pars, _n, _i; option `Copyright (c) 2000 by Waterloo Maple Inc. All rights reserved.`; if 1 < nargs then error "invalid input: too many arguments" end if; _EnvDSNumericSaveDigits := Digits; Digits := 15; if _EnvInFsolve = true then _xout := evalf[_EnvDSNumericSaveDigits](x_rkf45) else _xout := evalf(x_rkf45) end if; _dat := Array(1..4, {(1) = proc (_xin) local _xout, _dtbl, _dat, _vmap, _x0, _y0, _val, _dig, _n, _ne, _nd, _nv, _pars, _ini, _par, _i, _j, _k, _src; option `Copyright (c) 2002 by Waterloo Maple Inc. All rights reserved.`; table( [( "complex" ) = false ] ) _xout := _xin; _pars := []; _dtbl := array( 1 .. 4, [( 1 ) = (array( 1 .. 28, [( 1 ) = (datatype = float[8], order = C_order, storage = rectangular), ( 2 ) = (datatype = float[8], order = C_order, storage = rectangular), ( 3 ) = ([0, 0, 0, Array(1..0, 1..2, {}, datatype = float[8], order = C_order)]), ( 4 ) = (Array(1..65, {(1) = 1, (2) = 1, (3) = 0, (4) = 0, (5) = 0, (6) = 0, (7) = 1, (8) = 0, (9) = 0, (10) = 0, (11) = 0, (12) = 0, (13) = 0, (14) = 0, (15) = 0, (16) = 0, (17) = 0, (18) = 21, (19) = 30000, (20) = 0, (21) = 0, (22) = 1, (23) = 4, (24) = 0, (25) = 1, (26) = 15, (27) = 1, (28) = 0, (29) = 1, (30) = 3, (31) = 3, (32) = 0, (33) = 1, (34) = 0, (35) = 0, (36) = 0, (37) = 0, (38) = 0, (39) = 0, (40) = 0, (41) = 0, (42) = 0, (43) = 1, (44) = 0, (45) = 0, (46) = 0, (47) = 0, (48) = 0, (49) = 0, (50) = 50, (51) = 1, (52) = 0, (53) = 0, (54) = 0, (55) = 0, (56) = 0, (57) = 0, (58) = 0, (59) = 10000, (60) = 0, (61) = 1000, (62) = 0, (63) = 0, (64) = -1, (65) = 0}, datatype = integer[8])), ( 5 ) = (Array(1..28, {(1) = .0, (2) = 0.10e-5, (3) = .0, (4) = 0.500001e-14, (5) = .0, (6) = .16290418802201975, (7) = .0, (8) = 0.10e-5, (9) = .0, (10) = .0, (11) = .0, (12) = .0, (13) = 1.0, (14) = .0, (15) = .49999999999999, (16) = .0, (17) = 1.0, (18) = 1.0, (19) = .0, (20) = .0, (21) = 1.0, (22) = 1.0, (23) = .0, (24) = .0, (25) = 0.10e-14, (26) = .0, (27) = .0, (28) = .0}, datatype = float[8], order = C_order)), ( 6 ) = (Array(1..1, {(1) = 3.0}, datatype = float[8], order = C_order)), ( 7 ) = ([Array(1..4, 1..7, {(1, 1) = .0, (1, 2) = .203125, (1, 3) = .3046875, (1, 4) = .75, (1, 5) = .8125, (1, 6) = .40625, (1, 7) = .8125, (2, 1) = 0.6378173828125e-1, (2, 2) = .0, (2, 3) = .279296875, (2, 4) = .27237892150878906, (2, 5) = -0.9686851501464844e-1, (2, 6) = 0.1956939697265625e-1, (2, 7) = .5381584167480469, (3, 1) = 0.31890869140625e-1, (3, 2) = .0, (3, 3) = -.34375, (3, 4) = -.335235595703125, (3, 5) = .2296142578125, (3, 6) = .41748046875, (3, 7) = 11.480712890625, (4, 1) = 0.9710520505905151e-1, (4, 2) = .0, (4, 3) = .40350341796875, (4, 4) = 0.20297467708587646e-1, (4, 5) = -0.6054282188415527e-2, (4, 6) = -0.4770040512084961e-1, (4, 7) = .77858567237854}, datatype = float[8], order = C_order), Array(1..6, 1..6, {(1, 1) = .0, (1, 2) = .0, (1, 3) = .0, (1, 4) = .0, (1, 5) = .0, (1, 6) = 1.0, (2, 1) = .25, (2, 2) = .0, (2, 3) = .0, (2, 4) = .0, (2, 5) = .0, (2, 6) = 1.0, (3, 1) = .1875, (3, 2) = .5625, (3, 3) = .0, (3, 4) = .0, (3, 5) = .0, (3, 6) = 2.0, (4, 1) = .23583984375, (4, 2) = -.87890625, (4, 3) = .890625, (4, 4) = .0, (4, 5) = .0, (4, 6) = .2681884765625, (5, 1) = .1272735595703125, (5, 2) = -.5009765625, (5, 3) = .44921875, (5, 4) = -0.128936767578125e-1, (5, 5) = .0, (5, 6) = 0.626220703125e-1, (6, 1) = -0.927734375e-1, (6, 2) = .626220703125, (6, 3) = -.4326171875, (6, 4) = .1418304443359375, (6, 5) = -0.861053466796875e-1, (6, 6) = .3131103515625}, datatype = float[8], order = C_order), Array(1..6, {(1) = .0, (2) = .386, (3) = .21, (4) = .63, (5) = 1.0, (6) = 1.0}, datatype = float[8], order = C_order), Array(1..6, {(1) = .25, (2) = -.1043, (3) = .1035, (4) = -0.362e-1, (5) = .0, (6) = .0}, datatype = float[8], order = C_order), Array(1..6, 1..5, {(1, 1) = .0, (1, 2) = .0, (1, 3) = .0, (1, 4) = .0, (1, 5) = .0, (2, 1) = 1.544, (2, 2) = .0, (2, 3) = .0, (2, 4) = .0, (2, 5) = .0, (3, 1) = .9466785280815533, (3, 2) = .25570116989825814, (3, 3) = .0, (3, 4) = .0, (3, 5) = .0, (4, 1) = 3.3148251870684886, (4, 2) = 2.896124015972123, (4, 3) = .9986419139977808, (4, 4) = .0, (4, 5) = .0, (5, 1) = 1.2212245092262748, (5, 2) = 6.019134481287752, (5, 3) = 12.537083329320874, (5, 4) = -.687886036105895, (5, 5) = .0, (6, 1) = 1.2212245092262748, (6, 2) = 6.019134481287752, (6, 3) = 12.537083329320874, (6, 4) = -.687886036105895, (6, 5) = 1.0}, datatype = float[8], order = C_order), Array(1..6, 1..5, {(1, 1) = .0, (1, 2) = .0, (1, 3) = .0, (1, 4) = .0, (1, 5) = .0, (2, 1) = -5.6688, (2, 2) = .0, (2, 3) = .0, (2, 4) = .0, (2, 5) = .0, (3, 1) = -2.4300933568337584, (3, 2) = -.20635991570891224, (3, 3) = .0, (3, 4) = .0, (3, 5) = .0, (4, 1) = -.10735290581452621, (4, 2) = -9.594562251021896, (4, 3) = -20.470286148096154, (4, 4) = .0, (4, 5) = .0, (5, 1) = 7.496443313968615, (5, 2) = -10.246804314641219, (5, 3) = -33.99990352819906, (5, 4) = 11.708908932061595, (5, 5) = .0, (6, 1) = 8.083246795922411, (6, 2) = -7.981132988062785, (6, 3) = -31.52159432874373, (6, 4) = 16.319305431231363, (6, 5) = -6.0588182388340535}, datatype = float[8], order = C_order), Array(1..3, 1..5, {(1, 1) = .0, (1, 2) = .0, (1, 3) = .0, (1, 4) = .0, (1, 5) = .0, (2, 1) = 10.126235083446911, (2, 2) = -7.487995877607633, (2, 3) = -34.800918615557414, (2, 4) = -7.9927717075687275, (2, 5) = 1.0251377232956207, (3, 1) = -.6762803392806898, (3, 2) = 6.087714651678606, (3, 3) = 16.43084320892463, (3, 4) = 24.767225114183653, (3, 5) = -6.5943891257167815}, datatype = float[8], order = C_order)]), ( 9 ) = ([Array(1..1, {(1) = .1}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, 1..1, {(1, 1) = .0}, datatype = float[8], order = C_order), Array(1..1, 1..1, {(1, 1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, 1..1, {(1, 1) = .0}, datatype = float[8], order = C_order), Array(1..1, 1..6, {(1, 1) = .0, (1, 2) = .0, (1, 3) = .0, (1, 4) = .0, (1, 5) = .0, (1, 6) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = 0}, datatype = integer[8]), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..2, {(1) = .0, (2) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = 0}, datatype = integer[8])]), ( 8 ) = ([Array(1..1, {(1) = 3.0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), Array(1..1, {(1) = .0}, datatype = float[8], order = C_order), 0, 0]), ( 11 ) = (Array(1..6, 0..1, {(1, 1) = .0, (2, 0) = .0, (2, 1) = .0, (3, 0) = .0, (3, 1) = .0, (4, 0) = .0, (4, 1) = .0, (5, 0) = .0, (5, 1) = .0, (6, 0) = .0, (6, 1) = .0}, datatype = float[8], order = C_order)), ( 10 ) = ([proc (N, X, Y, YP) option `[Y[1] = y(x)]`; YP[1] := sin(X*Y[1]); 0 end proc, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), ( 13 ) = (), ( 12 ) = (), ( 15 ) = ("rkf45"), ( 14 ) = ([0, 0]), ( 18 ) = ([]), ( 19 ) = (0), ( 16 ) = ([0, 0, 0, 0, 0, 0, []]), ( 17 ) = ([proc (N, X, Y, YP) option `[Y[1] = y(x)]`; YP[1] := sin(X*Y[1]); 0 end proc, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), ( 22 ) = (0), ( 23 ) = (0), ( 20 ) = ([]), ( 21 ) = (0), ( 27 ) = (""), ( 26 ) = (Array(1..0, {})), ( 25 ) = (Array(1..0, {})), ( 24 ) = (0), ( 28 ) = (0)  ] ))  ] ); _y0 := Array(0..1, {(1) = 0.}); _vmap := array( 1 .. 1, [( 1 ) = (1)  ] ); _x0 := _dtbl[1][5][5]; _n := _dtbl[1][4][1]; _ne := _dtbl[1][4][3]; _nd := _dtbl[1][4][4]; _nv := _dtbl[1][4][16]; if not type(_xout, 'numeric') then if member(_xout, ["start", "left", "right"]) then if _Env_smart_dsolve_numeric = true or _dtbl[1][4][10] = 1 then if _xout = "left" then if type(_dtbl[2], 'table') then return _dtbl[2][5][1] end if elif _xout = "right" then if type(_dtbl[3], 'table') then return _dtbl[3][5][1] end if end if end if; return _dtbl[1][5][5] elif _xout = "method" then return _dtbl[1][15] elif _xout = "storage" then return evalb(_dtbl[1][4][10] = 1) elif _xout = "leftdata" then if not type(_dtbl[2], 'array') then return NULL else return eval(_dtbl[2]) end if elif _xout = "rightdata" then if not type(_dtbl[3], 'array') then return NULL else return eval(_dtbl[3]) end if elif _xout = "enginedata" then return eval(_dtbl[1]) elif _xout = "enginereset" then _dtbl[2] := evaln(_dtbl[2]); _dtbl[3] := evaln(_dtbl[3]); return NULL elif _xout = "initial" then return procname(_y0[0]) elif _xout = "laxtol" then return _dtbl[`if`(member(_dtbl[4], {2, 3}), _dtbl[4], 1)][5][18] elif _xout = "numfun" then return `if`(member(_dtbl[4], {2, 3}), _dtbl[_dtbl[4]][4][18], 0) elif _xout = "parameters" then return [seq(_y0[_n+_i], _i = 1 .. nops(_pars))] elif _xout = "initial_and_parameters" then return procname(_y0[0]), [seq(_y0[_n+_i], _i = 1 .. nops(_pars))] elif _xout = "last" then if _dtbl[4] <> 2 and _dtbl[4] <> 3 or _x0-_dtbl[_dtbl[4]][5][1] = 0. then error "no information is available on last computed point" else _xout := _dtbl[_dtbl[4]][5][1] end if elif _xout = "function" then if _dtbl[1][4][33]-2. = 0 then return eval(_dtbl[1][10], 1) else return eval(_dtbl[1][10][1], 1) end if elif _xout = "map" then return copy(_vmap) elif type(_xin, `=`) and type(rhs(_xin), 'list') and member(lhs(_xin), {"initial", "parameters", "initial_and_parameters"}) then _ini, _par := [], []; if lhs(_xin) = "initial" then _ini := rhs(_xin) elif lhs(_xin) = "parameters" then _par := rhs(_xin) elif select(type, rhs(_xin), `=`) <> [] then _par, _ini := selectremove(type, rhs(_xin), `=`) elif nops(rhs(_xin)) < nops(_pars)+1 then error "insufficient data for specification of initial and parameters" else _par := rhs(_xin)[-nops(_pars) .. -1]; _ini := rhs(_xin)[1 .. -nops(_pars)-1] end if; _xout := lhs(_xout); _i := false; if _par <> [] then _i := `dsolve/numeric/process_parameters`(_n, _pars, _par, _y0) end if; if _ini <> [] then _i := `dsolve/numeric/process_initial`(_n-_ne, _ini, _y0, _pars, _vmap) or _i end if; if _i then `dsolve/numeric/SC/reinitialize`(_dtbl, _y0, _n, procname, _pars); if _Env_smart_dsolve_numeric = true and type(_y0[0], 'numeric') and _dtbl[1][4][10] <> 1 then procname("right") := _y0[0]; procname("left") := _y0[0] end if end if; if _xout = "initial" then return [_y0[0], seq(_y0[_vmap[_i]], _i = 1 .. _n-_ne)] elif _xout = "parameters" then return [seq(_y0[_n+_i], _i = 1 .. nops(_pars))] else return [_y0[0], seq(_y0[_vmap[_i]], _i = 1 .. _n-_ne)], [seq(_y0[_n+_i], _i = 1 .. nops(_pars))] end if elif _xin = "eventstop" then if _nv = 0 then error "this solution has no events" end if; _i := _dtbl[4]; if _i <> 2 and _i <> 3 then return 0 end if; if _dtbl[_i][4][10] = 1 and assigned(_dtbl[5-_i]) and _dtbl[_i][4][9] < 100 and 100 <= _dtbl[5-_i][4][9] then _i := 5-_i; _dtbl[4] := _i; _j := round(_dtbl[_i][4][17]); return round(_dtbl[_i][3][1][_j, 1]) elif 100 <= _dtbl[_i][4][9] then _j := round(_dtbl[_i][4][17]); return round(_dtbl[_i][3][1][_j, 1]) else return 0 end if elif _xin = "eventstatus" then if _nv = 0 then error "this solution has no events" end if; _i := [selectremove(proc (a) options operator, arrow; _dtbl[1][3][1][a, 7] = 1 end proc, {seq(_j, _j = 1 .. round(_dtbl[1][3][1][_nv+1, 1]))})]; return ':-enabled' = _i[1], ':-disabled' = _i[2] elif _xin = "eventclear" then if _nv = 0 then error "this solution has no events" end if; _i := _dtbl[4]; if _i <> 2 and _i <> 3 then error "no events to clear" end if; if _dtbl[_i][4][10] = 1 and assigned(_dtbl[5-_i]) and _dtbl[_i][4][9] < 100 and 100 < _dtbl[5-_i][4][9] then _dtbl[4] := 5-_i; _i := 5-_i end if; if _dtbl[_i][4][9] < 100 then error "no events to clear" elif _nv < _dtbl[_i][4][9]-100 then error "event error condition cannot be cleared" else _j := _dtbl[_i][4][9]-100; if irem(round(_dtbl[_i][3][1][_j, 4]), 2) = 1 then error "retriggerable events cannot be cleared" end if; _j := round(_dtbl[_i][3][1][_j, 1]); for _k to _nv do if _dtbl[_i][3][1][_k, 1] = _j then if _dtbl[_i][3][1][_k, 2] = 3 then error "range events cannot be cleared" end if; _dtbl[_i][3][1][_k, 8] := _dtbl[_i][3][1][_nv+1, 8] end if end do; _dtbl[_i][4][17] := 0; _dtbl[_i][4][9] := 0; if _dtbl[1][4][10] = 1 then if _i = 2 then try procname(procname("left")) catch:  end try else try procname(procname("right")) catch:  end try end if end if end if; return  elif type(_xin, `=`) and member(lhs(_xin), {"eventdisable", "eventenable"}) then if _nv = 0 then error "this solution has no events" end if; if type(rhs(_xin), {('list')('posint'), ('set')('posint')}) then _i := {op(rhs(_xin))} elif type(rhs(_xin), 'posint') then _i := {rhs(_xin)} else error "event identifiers must be integers in the range 1..%1", round(_dtbl[1][3][1][_nv+1, 1]) end if; if select(proc (a) options operator, arrow; _nv < a end proc, _i) <> {} then error "event identifiers must be integers in the range 1..%1", round(_dtbl[1][3][1][_nv+1, 1]) end if; _k := {}; for _j to _nv do if member(round(_dtbl[1][3][1][_j, 1]), _i) then _k := `union`(_k, {_j}) end if end do; _i := _k; if lhs(_xin) = "eventdisable" then _dtbl[4] := 0; _j := [evalb(assigned(_dtbl[2]) and member(_dtbl[2][4][17], _i)), evalb(assigned(_dtbl[3]) and member(_dtbl[3][4][17], _i))]; for _k in _i do _dtbl[1][3][1][_k, 7] := 0; if assigned(_dtbl[2]) then _dtbl[2][3][1][_k, 7] := 0 end if; if assigned(_dtbl[3]) then _dtbl[3][3][1][_k, 7] := 0 end if end do; if _j[1] then for _k to _nv+1 do if _k <= _nv and not type(_dtbl[2][3][4][_k, 1], 'undefined') then userinfo(3, {'events', 'eventreset'}, `reinit #2, event code `, _k, ` to defined init `, _dtbl[2][3][4][_k, 1]); _dtbl[2][3][1][_k, 8] := _dtbl[2][3][4][_k, 1] elif _dtbl[2][3][1][_k, 2] = 0 and irem(iquo(round(_dtbl[2][3][1][_k, 4]), 32), 2) = 1 then userinfo(3, {'events', 'eventreset'}, `reinit #2, event code `, _k, ` to rate hysteresis init `, _dtbl[2][5][24]); _dtbl[2][3][1][_k, 8] := _dtbl[2][5][24] elif _dtbl[2][3][1][_k, 2] = 0 and irem(iquo(round(_dtbl[2][3][1][_k, 4]), 2), 2) = 0 then userinfo(3, {'events', 'eventreset'}, `reinit #2, event code `, _k, ` to initial init `, _x0); _dtbl[2][3][1][_k, 8] := _x0 else userinfo(3, {'events', 'eventreset'}, `reinit #2, event code `, _k, ` to fireinitial init `, _x0-1); _dtbl[2][3][1][_k, 8] := _x0-1 end if end do; _dtbl[2][4][17] := 0; _dtbl[2][4][9] := 0; if _dtbl[1][4][10] = 1 then procname(procname("left")) end if end if; if _j[2] then for _k to _nv+1 do if _k <= _nv and not type(_dtbl[3][3][4][_k, 2], 'undefined') then userinfo(3, {'events', 'eventreset'}, `reinit #3, event code `, _k, ` to defined init `, _dtbl[3][3][4][_k, 2]); _dtbl[3][3][1][_k, 8] := _dtbl[3][3][4][_k, 2] elif _dtbl[3][3][1][_k, 2] = 0 and irem(iquo(round(_dtbl[3][3][1][_k, 4]), 32), 2) = 1 then userinfo(3, {'events', 'eventreset'}, `reinit #3, event code `, _k, ` to rate hysteresis init `, _dtbl[3][5][24]); _dtbl[3][3][1][_k, 8] := _dtbl[3][5][24] elif _dtbl[3][3][1][_k, 2] = 0 and irem(iquo(round(_dtbl[3][3][1][_k, 4]), 2), 2) = 0 then userinfo(3, {'events', 'eventreset'}, `reinit #3, event code `, _k, ` to initial init `, _x0); _dtbl[3][3][1][_k, 8] := _x0 else userinfo(3, {'events', 'eventreset'}, `reinit #3, event code `, _k, ` to fireinitial init `, _x0+1); _dtbl[3][3][1][_k, 8] := _x0+1 end if end do; _dtbl[3][4][17] := 0; _dtbl[3][4][9] := 0; if _dtbl[1][4][10] = 1 then procname(procname("right")) end if end if else for _k in _i do _dtbl[1][3][1][_k, 7] := 1 end do; _dtbl[2] := evaln(_dtbl[2]); _dtbl[3] := evaln(_dtbl[3]); _dtbl[4] := 0; if _dtbl[1][4][10] = 1 then if _x0 <= procname("right") then try procname(procname("right")) catch:  end try end if; if procname("left") <= _x0 then try procname(procname("left")) catch:  end try end if end if end if; return  elif type(_xin, `=`) and lhs(_xin) = "eventfired" then if not type(rhs(_xin), 'list') then error "'eventfired' must be specified as a list" end if; if _nv = 0 then error "this solution has no events" end if; if _dtbl[4] <> 2 and _dtbl[4] <> 3 then error "'direction' must be set prior to calling/setting 'eventfired'" end if; _i := _dtbl[4]; _val := NULL; if not assigned(_EnvEventRetriggerWarned) then _EnvEventRetriggerWarned := false end if; for _k in rhs(_xin) do if type(_k, 'integer') then _src := _k elif type(_k, 'integer' = 'anything') and type(evalf(rhs(_k)), 'numeric') then _k := lhs(_k) = evalf[max(Digits, 18)](rhs(_k)); _src := lhs(_k) else error "'eventfired' entry is not valid: %1", _k end if; if _src < 1 or round(_dtbl[1][3][1][_nv+1, 1]) < _src then error "event identifiers must be integers in the range 1..%1", round(_dtbl[1][3][1][_nv+1, 1]) end if; _src := {seq(`if`(_dtbl[1][3][1][_j, 1]-_src = 0., _j, NULL), _j = 1 .. _nv)}; if nops(_src) <> 1 then error "'eventfired' can only be set/queried for root-finding events and time/interval events" end if; _src := _src[1]; if _dtbl[1][3][1][_src, 2] <> 0. and _dtbl[1][3][1][_src, 2]-2. <> 0. then error "'eventfired' can only be set/queried for root-finding events and time/interval events" elif irem(round(_dtbl[1][3][1][_src, 4]), 2) = 1 then if _EnvEventRetriggerWarned = false then WARNING(`'eventfired' has no effect on events that retrigger`) end if; _EnvEventRetriggerWarned := true end if; if _dtbl[_i][3][1][_src, 2] = 0 and irem(iquo(round(_dtbl[_i][3][1][_src, 4]), 32), 2) = 1 then _val := _val, undefined elif type(_dtbl[_i][3][4][_src, _i-1], 'undefined') or _i = 2 and _dtbl[2][3][1][_src, 8] < _dtbl[2][3][4][_src, 1] or _i = 3 and _dtbl[3][3][4][_src, 2] < _dtbl[3][3][1][_src, 8] then _val := _val, _dtbl[_i][3][1][_src, 8] else _val := _val, _dtbl[_i][3][4][_src, _i-1] end if; if type(_k, `=`) then if _dtbl[_i][3][1][_src, 2] = 0 and irem(iquo(round(_dtbl[_i][3][1][_src, 4]), 32), 2) = 1 then error "cannot set event code for a rate hysteresis event" end if; userinfo(3, {'events', 'eventreset'}, `manual set event code `, _src, ` to value `, rhs(_k)); _dtbl[_i][3][1][_src, 8] := rhs(_k); _dtbl[_i][3][4][_src, _i-1] := rhs(_k) end if end do; return [_val] elif type(_xin, `=`) and lhs(_xin) = "direction" then if not member(rhs(_xin), {-1, 1, ':-left', ':-right'}) then error "'direction' must be specified as either '1' or 'right' (positive) or '-1' or 'left' (negative)" end if; _src := `if`(_dtbl[4] = 2, -1, `if`(_dtbl[4] = 3, 1, undefined)); _i := `if`(member(rhs(_xin), {1, ':-right'}), 3, 2); _dtbl[4] := _i; _dtbl[_i] := `dsolve/numeric/SC/IVPdcopy`(_dtbl[1], `if`(assigned(_dtbl[_i]), _dtbl[_i], NULL)); if 0 < _nv then for _j to _nv+1 do if _j <= _nv and not type(_dtbl[_i][3][4][_j, _i-1], 'undefined') then userinfo(3, {'events', 'eventreset'}, `reinit #4, event code `, _j, ` to defined init `, _dtbl[_i][3][4][_j, _i-1]); _dtbl[_i][3][1][_j, 8] := _dtbl[_i][3][4][_j, _i-1] elif _dtbl[_i][3][1][_j, 2] = 0 and irem(iquo(round(_dtbl[_i][3][1][_j, 4]), 32), 2) = 1 then userinfo(3, {'events', 'eventreset'}, `reinit #4, event code `, _j, ` to rate hysteresis init `, _dtbl[_i][5][24]); _dtbl[_i][3][1][_j, 8] := _dtbl[_i][5][24] elif _dtbl[_i][3][1][_j, 2] = 0 and irem(iquo(round(_dtbl[_i][3][1][_j, 4]), 2), 2) = 0 then userinfo(3, {'events', 'eventreset'}, `reinit #4, event code `, _j, ` to initial init `, _x0); _dtbl[_i][3][1][_j, 8] := _x0 else userinfo(3, {'events', 'eventreset'}, `reinit #4, event code `, _j, ` to fireinitial init `, _x0-2*_i+5.0); _dtbl[_i][3][1][_j, 8] := _x0-2*_i+5.0 end if end do end if; return _src elif _xin = "eventcount" then if _dtbl[1][3][1] = 0 or _dtbl[4] <> 2 and _dtbl[4] <> 3 then return 0 else return round(_dtbl[_dtbl[4]][3][1][_nv+1, 12]) end if elif type(_xin, `=`) and lhs(_xin) = "setdatacallback" then if not type(rhs(_xin), 'nonegint') then error "data callback must be a nonnegative integer (address)" end if; _dtbl[1][28] := rhs(_xin) else return "procname" end if end if; if _xout = _x0 then return [_x0, seq(evalf(_dtbl[1][6][_vmap[_i]]), _i = 1 .. _n-_ne)] end if; _i := `if`(_x0 <= _xout, 3, 2); if _xin = "last" and 0 < _dtbl[_i][4][9] and _dtbl[_i][4][9] < 100 then _dat := eval(_dtbl[_i], 2); _j := _dat[4][20]; return [_dat[11][_j, 0], seq(_dat[11][_j, _vmap[_i]], _i = 1 .. _n-_ne-_nd), seq(_dat[8][1][_vmap[_i]], _i = _n-_ne-_nd+1 .. _n-_ne)] end if; if not type(_dtbl[_i], 'array') then _dtbl[_i] := `dsolve/numeric/SC/IVPdcopy`(_dtbl[1], `if`(assigned(_dtbl[_i]), _dtbl[_i], NULL)); if 0 < _nv then for _j to _nv+1 do if _j <= _nv and not type(_dtbl[_i][3][4][_j, _i-1], 'undefined') then userinfo(3, {'events', 'eventreset'}, `reinit #5, event code `, _j, ` to defined init `, _dtbl[_i][3][4][_j, _i-1]); _dtbl[_i][3][1][_j, 8] := _dtbl[_i][3][4][_j, _i-1] elif _dtbl[_i][3][1][_j, 2] = 0 and irem(iquo(round(_dtbl[_i][3][1][_j, 4]), 32), 2) = 1 then userinfo(3, {'events', 'eventreset'}, `reinit #5, event code `, _j, ` to rate hysteresis init `, _dtbl[_i][5][24]); _dtbl[_i][3][1][_j, 8] := _dtbl[_i][5][24] elif _dtbl[_i][3][1][_j, 2] = 0 and irem(iquo(round(_dtbl[_i][3][1][_j, 4]), 2), 2) = 0 then userinfo(3, {'events', 'eventreset'}, `reinit #5, event code `, _j, ` to initial init `, _x0); _dtbl[_i][3][1][_j, 8] := _x0 else userinfo(3, {'events', 'eventreset'}, `reinit #5, event code `, _j, ` to fireinitial init `, _x0-2*_i+5.0); _dtbl[_i][3][1][_j, 8] := _x0-2*_i+5.0 end if end do end if end if; if _xin <> "last" then if 0 < 0 then if `dsolve/numeric/checkglobals`(op(_dtbl[1][14]), _pars, _n, _y0) then `dsolve/numeric/SC/reinitialize`(_dtbl, _y0, _n, procname, _pars, _i) end if end if; if _dtbl[1][4][7] = 0 then error "parameters must be initialized before solution can be computed" end if end if; _dat := eval(_dtbl[_i], 2); _dtbl[4] := _i; try _src := `dsolve/numeric/SC/IVPrun`(_dat, _xout) catch: userinfo(2, `dsolve/debug`, print(`Exception in solnproc:`, [lastexception][2 .. -1])); error  end try; if _dat[17] <> _dtbl[1][17] then _dtbl[1][17] := _dat[17]; _dtbl[1][10] := _dat[10] end if; if _src = 0 and 100 < _dat[4][9] then _val := _dat[3][1][_nv+1, 8] else _val := _dat[11][_dat[4][20], 0] end if; if _src <> 0 or _dat[4][9] <= 0 then _dtbl[1][5][1] := _xout else _dtbl[1][5][1] := _val end if; if _i = 3 and _val < _xout then Rounding := -infinity; if _dat[4][9] = 1 then error "cannot evaluate the solution further right of %1, probably a singularity", evalf[8](_val) elif _dat[4][9] = 2 then error "cannot evaluate the solution further right of %1, maxfun limit exceeded (see <a href='http://www.maplesoft.com/support/help/search.aspx?term=dsolve,maxfun' target='_new'>?dsolve,maxfun</a> for details)", evalf[8](_val) elif _dat[4][9] = 3 then if _dat[4][25] = 3 then error "cannot evaluate the solution past the initial point, problem may be initially singular or improperly set up" else error "cannot evaluate the solution past the initial point, problem may be complex, initially singular or improperly set up" end if elif _dat[4][9] = 4 then error "cannot evaluate the solution further right of %1, accuracy goal cannot be achieved with specified 'minstep'", evalf[8](_val) elif _dat[4][9] = 5 then error "cannot evaluate the solution further right of %1, too many step failures, tolerances may be too loose for problem", evalf[8](_val) elif _dat[4][9] = 6 then error "cannot evaluate the solution further right of %1, cannot downgrade delay storage for problems with delay derivative order > 1, try increasing delaypts", evalf[8](_val) elif _dat[4][9] = 10 then error "cannot evaluate the solution further right of %1, interrupt requested", evalf[8](_val) elif 100 < _dat[4][9] then if _dat[4][9]-100 = _nv+1 then error "constraint projection failure on event at t=%1", evalf[8](_val) elif _dat[4][9]-100 = _nv+2 then error "index-1 and derivative evaluation failure on event at t=%1", evalf[8](_val) elif _dat[4][9]-100 = _nv+3 then error "maximum number of event iterations reached (%1) at t=%2", round(_dat[3][1][_nv+1, 3]), evalf[8](_val) else if _Env_dsolve_nowarnstop <> true then `dsolve/numeric/warning`(StringTools:-FormatMessage("cannot evaluate the solution further right of %1, event #%2 triggered a halt", evalf[8](_val), round(_dat[3][1][_dat[4][9]-100, 1]))) end if; Rounding := 'nearest'; _xout := _val end if else error "cannot evaluate the solution further right of %1", evalf[8](_val) end if elif _i = 2 and _xout < _val then Rounding := infinity; if _dat[4][9] = 1 then error "cannot evaluate the solution further left of %1, probably a singularity", evalf[8](_val) elif _dat[4][9] = 2 then error "cannot evaluate the solution further left of %1, maxfun limit exceeded (see <a href='http://www.maplesoft.com/support/help/search.aspx?term=dsolve,maxfun' target='_new'>?dsolve,maxfun</a> for details)", evalf[8](_val) elif _dat[4][9] = 3 then if _dat[4][25] = 3 then error "cannot evaluate the solution past the initial point, problem may be initially singular or improperly set up" else error "cannot evaluate the solution past the initial point, problem may be complex, initially singular or improperly set up" end if elif _dat[4][9] = 4 then error "cannot evaluate the solution further left of %1, accuracy goal cannot be achieved with specified 'minstep'", evalf[8](_val) elif _dat[4][9] = 5 then error "cannot evaluate the solution further left of %1, too many step failures, tolerances may be too loose for problem", evalf[8](_val) elif _dat[4][9] = 6 then error "cannot evaluate the solution further left of %1, cannot downgrade delay storage for problems with delay derivative order > 1, try increasing delaypts", evalf[8](_val) elif _dat[4][9] = 10 then error "cannot evaluate the solution further right of %1, interrupt requested", evalf[8](_val) elif 100 < _dat[4][9] then if _dat[4][9]-100 = _nv+1 then error "constraint projection failure on event at t=%1", evalf[8](_val) elif _dat[4][9]-100 = _nv+2 then error "index-1 and derivative evaluation failure on event at t=%1", evalf[8](_val) elif _dat[4][9]-100 = _nv+3 then error "maximum number of event iterations reached (%1) at t=%2", round(_dat[3][1][_nv+1, 3]), evalf[8](_val) else if _Env_dsolve_nowarnstop <> true then `dsolve/numeric/warning`(StringTools:-FormatMessage("cannot evaluate the solution further left of %1, event #%2 triggered a halt", evalf[8](_val), round(_dat[3][1][_dat[4][9]-100, 1]))) end if; Rounding := 'nearest'; _xout := _val end if else error "cannot evaluate the solution further left of %1", evalf[8](_val) end if end if; if _EnvInFsolve = true then _dig := _dat[4][26]; if type(_EnvDSNumericSaveDigits, 'posint') then _dat[4][26] := _EnvDSNumericSaveDigits else _dat[4][26] := Digits end if; _Env_dsolve_SC_native := true; if _dat[4][25] = 1 then _i := 1; _dat[4][25] := 2 else _i := _dat[4][25] end if; _val := `dsolve/numeric/SC/IVPval`(_dat, _xout, _src); _dat[4][25] := _i; _dat[4][26] := _dig; [_xout, seq(_val[_vmap[_i]], _i = 1 .. _n-_ne)] else Digits := _dat[4][26]; _val := `dsolve/numeric/SC/IVPval`(eval(_dat, 2), _xout, _src); [_xout, seq(_val[_vmap[_i]], _i = 1 .. _n-_ne)] end if end proc, (2) = Array(0..0, {}), (3) = [x, y(x)], (4) = []}); _vars := _dat[3]; _pars := map(lhs, _dat[4]); _n := nops(_vars)-1; _solnproc := _dat[1]; if not type(_xout, 'numeric') then if member(x_rkf45, ["start", 'start', "method", 'method', "left", 'left', "right", 'right', "leftdata", "rightdata", "enginedata", "eventstop", 'eventstop', "eventclear", 'eventclear', "eventstatus", 'eventstatus', "eventcount", 'eventcount', "laxtol", 'laxtol', "numfun", 'numfun', NULL]) then _res := _solnproc(convert(x_rkf45, 'string')); if 1 < nops([_res]) then return _res elif type(_res, 'array') then return eval(_res, 1) elif _res <> "procname" then return _res end if elif member(x_rkf45, ["last", 'last', "initial", 'initial', "parameters", 'parameters', "initial_and_parameters", 'initial_and_parameters', NULL]) then _xout := convert(x_rkf45, 'string'); _res := _solnproc(_xout); if _xout = "parameters" then return [seq(_pars[_i] = _res[_i], _i = 1 .. nops(_pars))] elif _xout = "initial_and_parameters" then return [seq(_vars[_i+1] = [_res][1][_i+1], _i = 0 .. _n), seq(_pars[_i] = [_res][2][_i], _i = 1 .. nops(_pars))] else return [seq(_vars[_i+1] = _res[_i+1], _i = 0 .. _n)] end if elif type(_xout, `=`) and member(lhs(_xout), ["initial", 'initial', "parameters", 'parameters', "initial_and_parameters", 'initial_and_parameters', NULL]) then _xout := convert(lhs(x_rkf45), 'string') = rhs(x_rkf45); if type(rhs(_xout), 'list') then _res := _solnproc(_xout) else error "initial and/or parameter values must be specified in a list" end if; if lhs(_xout) = "initial" then return [seq(_vars[_i+1] = _res[_i+1], _i = 0 .. _n)] elif lhs(_xout) = "parameters" then return [seq(_pars[_i] = _res[_i], _i = 1 .. nops(_pars))] else return [seq(_vars[_i+1] = [_res][1][_i+1], _i = 0 .. _n), seq(_pars[_i] = [_res][2][_i], _i = 1 .. nops(_pars))] end if elif type(_xout, `=`) and member(lhs(_xout), ["eventdisable", 'eventdisable', "eventenable", 'eventenable', "eventfired", 'eventfired', "direction", 'direction', NULL]) then return _solnproc(convert(lhs(x_rkf45), 'string') = rhs(x_rkf45)) elif _xout = "solnprocedure" then return eval(_solnproc) elif _xout = "sysvars" then return _vars end if; if procname <> unknown then return ('procname')(x_rkf45) else _ndsol := 1; _ndsol := _ndsol; _ndsol := pointto(_dat[2][0]); return ('_ndsol')(x_rkf45) end if end if; try _res := _solnproc(_xout); [seq(_vars[_i+1] = _res[_i+1], _i = 0 .. _n)] catch: error  end try end proc

(6)

[soln(1), soln(1.5), soln(2), soln(2.5), soln(3), soln(3.5), soln(4), soln(4.5), soln(5)]

[[x = 1., y(x) = HFloat(3.5280317971877286)], [x = 1.5, y(x) = HFloat(3.1226400064202693)], [x = 2., y(x) = HFloat(2.653970420106217)], [x = 2.5, y(x) = HFloat(2.323175669304077)], [x = 3., y(x) = HFloat(2.3019187052877816)], [x = 3.5, y(x) = HFloat(2.6587033583656714)], [x = 4., y(x) = HFloat(2.497876146260152)], [x = 4.5, y(x) = HFloat(2.220305976552359)], [x = 5., y(x) = HFloat(1.9758297601444128)]]

(7)

p1 := odeplot(soln, [x, y(x)], x = 0 .. 5, color = magenta, thickness = 2, scaling = constrained, view = [0 .. 5, 0 .. 5])

 

p2 := dfieldplot(ODE2, [y(x)], x = 0 .. 5, y = 0 .. 5, color = blue, scaling = constrained)

display(p1, p2)

 

DEplot(ODE2, y(x), x = 0 .. 5, y = 0 .. 5, [[y(0) = 3]], linecolor = red, color = blue, scaling = constrained, axes = boxed)

 

Construct approximate solutions for x from 0 to 5 to the initial problem 2 using Euler's method with the three different step sizes Δx=0.5, 0.25, 0.125

f := proc (x, y) options operator, arrow; sin(x*y) end proc

proc (x, y) options operator, arrow; sin(y*x) end proc

(8)

Eulermethod := proc (f, x_start, y_start, dx, n_total) local x, y, Y, i, k; x[1] := x_start; y[1] := y_start; for i to n_total do y[i+1] := y[i]+f(x[i], y[i])*dx; x[i+1] := x[1]+i*dx end do; Y := [seq([x[k], y[k]], k = 1 .. n_total)]; return Y end proc

proc (f, x_start, y_start, dx, n_total) local x, y, Y, i, k; x[1] := x_start; y[1] := y_start; for i to n_total do y[i+1] := y[i]+f(x[i], y[i])*dx; x[i+1] := x[1]+i*dx end do; Y := [seq([x[k], y[k]], k = 1 .. n_total)]; return Y end proc

(9)

NULL

NULL

NULL

NULL

A1 := Eulermethod(f, 0, 3, .5, 10)

[[0, 3], [.5, 3.], [1.0, 3.498747493], [1.5, 3.323942476], [2.0, 2.842530099], [2.5, 2.560983065], [3.0, 2.620477947], [3.5, 3.120464063], [4.0, 2.621830593], [4.5, 2.185032319]]

(10)

A2 := Eulermethod(f, 0, 3, .25, 20)

[[0, 3], [.25, 3.], [.50, 3.170409690], [.75, 3.420383740], [1.00, 3.556616077], [1.25, 3.455813236], [1.50, 3.224836021], [1.75, 2.976782400], [2.00, 2.757025820], [2.25, 2.583147563], [2.50, 2.469680146], [2.75, 2.442487816], [3.00, 2.547535655], [3.25, 2.791971512], [3.50, 2.877900373], [3.75, 2.727027361], [4.00, 2.547414295], [4.25, 2.374301829], [4.50, 2.219839448], [4.75, 2.086091178]]

(11)

A3 := Eulermethod(f, 0, 3, .125, 40)

[[0, 3], [.125, 3.], [.250, 3.045784066], [.375, 3.132030172], [.500, 3.247342837], [.625, 3.372168142], [.750, 3.479586272], [.875, 3.542983060], [1.000, 3.548166882], [1.125, 3.498733738], [1.250, 3.409546073], [1.375, 3.297015011], [1.500, 3.174012084], [1.625, 3.049159854], [1.750, 2.927817142], [1.875, 2.813241461], [2.000, 2.707496816], [2.125, 2.612101612], [2.250, 2.528513147], [2.375, 2.458549923], [2.500, 2.404840953], [2.625, 2.371369082], [2.750, 2.364080535], [2.875, 2.391119623], [3.000, 2.460798019], [3.125, 2.572154041], [3.250, 2.695044010], [3.375, 2.772263417], [3.500, 2.780805371], [3.625, 2.742906337], [3.750, 2.680985435], [3.875, 2.607451728], [4.000, 2.528940353], [4.125, 2.449278434], [4.250, 2.370825619], [4.375, 2.295054886], [4.500, 2.222824117], [4.625, 2.154537647], [4.750, 2.090275081], [4.875, 2.029905439]]

(12)

NULL

p3 := pointplot(A1, color = green, scaling = constrained, symbol = circle)

p4 := pointplot(A2, color = black, scaling = constrained, symbol = asterisk)

p5 := pointplot(A3, color = red, scaling = constrained, symbol = diamond)

NULL

display([p1, p3, p4, p5])

 

NULL

In this plot, the differences between the lines visually represent how using different step sizes affects the overall solution accuracy. The red points are closest to what a more accurate numerical solution would look like, while the green points are more of a rough approximation.

 

 

Problem 3 (IMPROVED EULER METHOD

``

 

 

 

ImprovedEulermethod := proc (f, x_start, y_start, dx, n_total) local x, y, Y, i, k, k1, k2; x[1] := x_start; y[1] := y_start; for i to n_total do k1 := f(x[i], y[i]); k2 := f(x[i]+dx, y[i]+k1*dx); y[i+1] := y[i]+(1/2)*dx*(k1+k2); x[i+1] := x[1]+i*dx end do; Y := [seq([x[k], y[k]], k = 1 .. n_total+1)]; return Y end proc

proc (f, x_start, y_start, dx, n_total) local x, y, Y, i, k, k1, k2; x[1] := x_start; y[1] := y_start; for i to n_total do k1 := f(x[i], y[i]); k2 := f(x[i]+dx, y[i]+k1*dx); y[i+1] := y[i]+(1/2)*dx*(k1+k2); x[i+1] := x[1]+i*dx end do; Y := [seq([x[k], y[k]], k = 1 .. n_total+1)]; return Y end proc

(13)

A := ImprovedEulermethod(f, 0, 3, .5, 10); B := ImprovedEulermethod(f, 0, 3, .25, 20); C := ImprovedEulermethod(f, 0, 3, .125, 40)

[[0, 3], [.125, 3.022892033], [.250, 3.089335383], [.375, 3.190999573], [.500, 3.311460714], [.625, 3.426126738], [.750, 3.508312296], [.875, 3.539992283], [1.000, 3.518184043], [1.125, 3.451931748], [1.250, 3.354946855], [1.375, 3.240089444], [1.500, 3.117181611], [1.625, 2.992925708], [1.750, 2.871597591], [1.875, 2.755823574], [2.000, 2.647215450], [2.125, 2.546845751], [2.250, 2.455612702], [2.375, 2.374560360], [2.500, 2.305227222], [2.625, 2.250113264], [2.750, 2.213376654], [2.875, 2.201814459], [3.000, 2.225589190], [3.125, 2.295322044], [3.250, 2.406184220], [3.375, 2.516909932], [3.500, 2.583378006], [3.625, 2.599915321], [3.750, 2.579967129], [3.875, 2.537160528], [4.000, 2.481052245], [4.125, 2.417781798], [4.250, 2.351265142], [4.375, 2.284028571], [4.500, 2.217702881], [4.625, 2.153313287], [4.750, 2.091461577], [4.875, 2.032452273], [5.000, 1.976386380]]

(14)

NULL

plot2 := pointplot(A, color = green, scaling = constrained, symbol = circle)

plot3 := pointplot(B, color = black, scaling = constrained, symbol = asterisk)

plot4 := pointplot(C, color = red, scaling = constrained, symbol = diamond)

NULL

display([p1, plot2, plot3, plot4])

 

The Improved Euler method, by averaging slopes, provides a significant improvement over the basic Euler method, particularly when the step size is relatively large.


Download Diff_equations.mw

This is a task from one forum:  “Let's mark an arbitrary point on the circle. Let's draw a segment from this point, perpendicular to the diameter, and draw a circle, the center of which is at this point, and the radius is equal to this segment. Let's mark the intersection point of the segment connecting the intersection points of the circles with the perpendicular segment. Prove that the locus of all such points is an ellipse.”
I wanted to get a picture of a numerically animated "proof" using Maple tools.

МАTH_HЕLP_PLANET.mw
 And in fact, it turned out that AB=2AC, or AC=BC.

Source codes (seen in the pdf file) for the paper "Maximal Gap Among Integers Having a Common Divisor with an Odd Semi-prime".

MaxGapTheorem2.pdf

The flag of Germany on the strip of the German mathematician August Ferdinand Möbius. Basically, it's just one way to represent flags of a certain type. It seemed that the flag looked good on the Mobius strip.
FLAG.mw

Hello!

I present a simple work-up of rolling a plane curve along a fixed plane curve in 2d space. Maple sources are attached.

Kind regards!

Source.zip

Today in class, we presented an exercise based on the paper titled "Analysis of regular and chaotic dynamics in a stochastic eco-epidemiological model" by Bashkirtseva, Ryashko, and Ryazanova (2020). In this exercise, we kept all parameters of the model the same as in the paper, but we varied the parameter β, which represents the rate of infection spread. The goal was to observe how changes in β impact the system's dynamics, particularly focusing on the transition between regular and chaotic behavior.

This exercise involves studying a mathematical model that appears in eco-epidemiology. The model is described by the following set of equations:

dx/dt = rx-bx^2-cxy-`&beta;xz`/(a+x)-a[1]*yz/(e+y)

dy/dt = -`&mu;y`+`&beta;xy`/(a+x)-a[2]*yz/(d+y)

" (dz)/(dt)=-mz+((c[1 ]a[1])[ ]xz)/(e[]+x)+((c[1 ]a[2])[ ]yz)/(d+y)"

 

where r, b, c, β, α,a[1],a[2], e, d, m, c[1], c[2], μ>0 are given parameters. This model generalizes the classic predator-prey system by incorporating disease dynamics within the prey population. The populations are divided into the following groups:

 

• 

Susceptible prey population (x): Individuals in the prey population that are healthy but can become infected by a disease.

• 

Infected prey population (y): Individuals in the prey population that are infected and can transmit the disease to others.

• 

Predator population (z): The predator population that feeds on both susceptible (x) and infected (y) prey.

 

The initial conditions are always x(0)=0.2, y(0)=0.05, z(0)=0.05,  and we will vary the parameter β.;

 

For this exercise, the parameters are fixed as follows:

 

"r=1,` b`=1,` c`=0.01, a=0.36 ,` a`[1]=0.01,` a`[2]=0.05,` e`[]=15,` m`=0.01,` d`=0.5,` c`[1]=2,` `c[2]==1,` mu`=0.4."

NULL

Task (a)

• 

Solve the system numerically for the given parameter values and initial conditions with β=0.6 over the time interval t2[0,20000].

• 

Plot the solutions x(t), y(t), and  z(t) over this time interval.

• 

Comment on the model's predictions, keeping in mind that the time units are usually days.

• 

Also, plot the trajectory in the 3D space (x,y,z).

 

restart

r := 1; b := 1; f := 0.1e-1; alpha := .36; a[1] := 0.1e-1; a[2] := 0.5e-1; e := 15; m := 0.1e-1; d := .5; c[1] := 2; c[2] := 1; mu := .4; beta := .6

sys := {diff(x(t), t) = r*x(t)-b*x(t)^2-f*x(t)*y(t)-beta*x(t)*y(t)/(alpha+x(t))-a[1]*x(t)*z(t)/(e+x(t)), diff(y(t), t) = -mu*y(t)+beta*x(t)*y(t)/(alpha+x(t))-a[2]*y(t)*z(t)/(d+y(t)), diff(z(t), t) = -m*z(t)+c[1]*a[1]*x(t)*z(t)/(e+x(t))+c[2]*a[2]*y(t)*z(t)/(d+y(t))}

{diff(x(t), t) = x(t)-x(t)^2-0.1e-1*x(t)*y(t)-.6*x(t)*y(t)/(.36+x(t))-0.1e-1*x(t)*z(t)/(15+x(t)), diff(y(t), t) = -.4*y(t)+.6*x(t)*y(t)/(.36+x(t))-0.5e-1*y(t)*z(t)/(.5+y(t)), diff(z(t), t) = -0.1e-1*z(t)+0.2e-1*x(t)*z(t)/(15+x(t))+0.5e-1*y(t)*z(t)/(.5+y(t))}

(1)

ics := {x(0) = .2, y(0) = 0.5e-1, z(0) = 0.5e-1}

{x(0) = .2, y(0) = 0.5e-1, z(0) = 0.5e-1}

(2)

NULL

sol := dsolve(`union`(sys, ics), {x(t), y(t), z(t)}, numeric, range = 0 .. 20000, maxfun = 0, output = listprocedure, abserr = 0.1e-7, relerr = 0.1e-7)

`[Length of output exceeds limit of 1000000]`

(3)

X := subs(sol, x(t)); Y := subs(sol, y(t)); Z := subs(sol, z(t))

``

plot('[X(t)]', t = 0 .. 20000, numpoints = 350, title = "Trajectory of x(t)", axes = boxed, gridlines, color = ["#40e0d0"])

 

plot('[Y(t)]', t = 0 .. 20000, numpoints = 350, title = "Trajectory", axes = boxed, gridlines, title = "Trajectory of y(t)", color = ["SteelBlue"])

 

``

plot('[Z(t)]', t = 0 .. 20000, numpoints = 350, title = "Trajectory", axes = boxed, gridlines, title = "Trajectory of Z(t)", color = "Black"); with(DEtools)

 

with(DEtools)

DEplot3d(sys, {x(t), y(t), z(t)}, t = 0 .. 20000, [[x(0) = .2, y(0) = 0.5e-1, z(0) = 0.5e-1]], numpoints = 35000, color = blue, thickness = 1, linestyle = solid)

 

Task (b)

• 

Repeat the study in part (a) with the same initial conditions but set β=0.61.

NULL

restart

r := 1; b := 1; f := 0.1e-1; alpha := .36; a[1] := 0.1e-1; a[2] := 0.5e-1; e := 15; m := 0.1e-1; d := .5; c[1] := 2; c[2] := 1; mu := .4; beta := .61

NULL

sys := {diff(x(t), t) = r*x(t)-b*x(t)^2-f*x(t)*y(t)-beta*x(t)*y(t)/(alpha+x(t))-a[1]*x(t)*z(t)/(e+x(t)), diff(y(t), t) = -mu*y(t)+beta*x(t)*y(t)/(alpha+x(t))-a[2]*y(t)*z(t)/(d+y(t)), diff(z(t), t) = -m*z(t)+c[1]*a[1]*x(t)*z(t)/(e+x(t))+c[2]*a[2]*y(t)*z(t)/(d+y(t))}

{diff(x(t), t) = x(t)-x(t)^2-0.1e-1*x(t)*y(t)-.61*x(t)*y(t)/(.36+x(t))-0.1e-1*x(t)*z(t)/(15+x(t)), diff(y(t), t) = -.4*y(t)+.61*x(t)*y(t)/(.36+x(t))-0.5e-1*y(t)*z(t)/(.5+y(t)), diff(z(t), t) = -0.1e-1*z(t)+0.2e-1*x(t)*z(t)/(15+x(t))+0.5e-1*y(t)*z(t)/(.5+y(t))}

(4)

NULL

ics := {x(0) = .2, y(0) = 0.5e-1, z(0) = 0.5e-1}

{x(0) = .2, y(0) = 0.5e-1, z(0) = 0.5e-1}

(5)

sol := dsolve(`union`(sys, ics), {x(t), y(t), z(t)}, numeric, range = 0 .. 20000, maxfun = 0, output = listprocedure, abserr = 0.1e-7, relerr = 0.1e-7)

`[Length of output exceeds limit of 1000000]`

(6)

X := subs(sol, x(t)); Y := subs(sol, y(t)); Z := subs(sol, z(t))

NULL

plot('[X(t)]', t = 0 .. 20000, numpoints = 350, title = "Trajectory of x(t)", axes = boxed, gridlines, color = ["Blue"])

 

plot('[Y(t)]', t = 0 .. 20000, numpoints = 350, title = "Trajectory of  Y(t)", axes = boxed, gridlines, color = "Red")

 

plot('[Z(t)]', t = 0 .. 20000, numpoints = 350, title = "Trajectory of  Y(t)", axes = boxed, gridlines, color = "Black")

 

NULL

with(DEtools)

DEplot3d(sys, {x(t), y(t), z(t)}, t = 0 .. 20000, [[x(0) = .2, y(0) = 0.5e-1, z(0) = 0.5e-1]], maxfun = 0, numpoints = 35000, color = blue, thickness = 1, linestyle = solid)

 

The rate of the infection spread is affected by the average number of contacts each person has (β=0.6) and increases depending on the degree of transmission within the population, in particular within specific subpopulations (such as those in rural areas). A detailed epidemiological study showed that the spread of infection is most significant in urban areas, where population density is higher, while in rural areas, the rate of infection remains relatively low. This suggests that additional public health measures are needed to reduce transmission in densely populated areas, particularly in regions with high population density such as cities

``

Download math_model_eco-epidemiology.mw

This is another attempt to tell about one way to solve the problem of inverse kinematics of a manipulator.  
We have a flat three-link manipulator. Its movement is determined by changing three angles - these are three control parameters. 1. the first link rotates around the black fixed point, 2. the second link rotates around the extreme movable point of the first link, 3. the third link − around the last point of the second link. These movable points are red. (The order of the links is from thick to thin.) The working point is green. For example, we need it to move along a circle. But the manipulator has one extra mobility (degree of freedom), that is, the problem has an infinite number of solutions. We have the ability to remove this extra degree of freedom mathematically. And this can also be done in an infinite number of ways.
Let us give two examples where the same manipulator performs the same movement of the working point in different ways. In one case the last red point moves in a straight line, and in the other case it moves in an ellipse. The result is the same. In the corresponding program texts, the manipulator model is described by a system of nonlinear equations f1, f2, f3, f4, f5 relative to the coordinates of the ends of the links (very easy to understand). The specific additional connection that takes away one degree of freedom is highlighted in blue. Equation of a circle in red color.

1.mw

2.mw


And as an elective. The same circle was obtained using a spatial 3-link manipulator with 5 degrees of freedom. In the last text, blue and red colors perform the same functions as in the previous texts.
3.mw

 

VerifyTools is a package that has been available in Maple for roughly 24 years, but until now it has never been documented, as it was originally intended for internal use only. Documentation for it will be included in the next release of Maple. Here is a preview:

VerifyTools is similar to the TypeTools package. A type is essentially a predicate that a single expression can either satisfy or not. Analogously, a verification is a predicate that applies to a pair of expressions, comparing them. Just as types can be combined to produce compound types, verifications can also be combined to produce compund verifications. New types can be created, retrieved, queried, or deleted using the commands AddType, GetType (or GetTypes), Exists, and RemoveType, respectively. Similarly in the VerifyTools package we can create, retrieve, query or delete verifications using AddVerification, GetVerification (or GetVerifications), Exists, and RemoveVerification.

The package command VerifyTools:-Verify is also available as the top-level Maple command verify which should already be familiar to expert Maple users. Similarly, the command VerifyTools:-IsVerification is also available as a type, that is,

VerifyTools:-IsVerification(ver);

will return the same as

type(ver, 'verification');

The following examples show what can be done with these commands. Note that in each example where the Verify command is used, it is equivalent to the top-level Maple command verify. (Also note that VerifyTools commands shown below will be slightly different compared to the Maple2024 version):

with(VerifyTools):

Suppose we want to create a verification which will checks that the length of a result has not increased compared to the expected result. We can do this using the AddVerification command:

AddVerification(length_not_increased, (a, b) -> evalb(length(a) <= length(b)));

First, we can check the existence of our new verification and get its value:

Exists(length_not_increased);

true

GetVerification(length_not_increased);

proc (a, b) options operator, arrow; evalb(length(a) <= length(b)) end proc

For named verifications, IsVerification is equivalent to Exists (since names are only recognized as verifications if an entry exists for them in the verification database):

IsVerification(length_not_increased);

true

On the other hand, a nontrivial structured verification can be checked with IsVerification,

IsVerification(boolean = length_not_increased);

true

whereas Exists only accepts names:

Exists(boolean = length_not_increased);

Error, invalid input: VerifyTools:-Exists expects its 1st argument, x, to be of type symbol, but received boolean = length_not_increased

The preceding command using Exists is also equivalent to the following type call:

type(boolean = length_not_increased, verification);

true

Now, let's use the new verification:

Verify(x + 1/x, (x^2 + 1)/x, length_not_increased);

true

Verify((x^2 + 1)/x, x + 1/x, length_not_increased);

false

Finally, let's remove the verification:

RemoveVerification(length_not_increased);

Exists(length_not_increased);

false

GetVerification(length_not_increased);

Error, (in VerifyTools:-GetVerification) length_not_increased is not a recognized verification

GetVerifications returns the list of all verifications known to the system:

GetVerifications();

[Array, FAIL, FrobeniusGroupId, Global, Matrix, MultiSet, PermGroup, RootOf, SmallGroupId, Vector, address, after, approx, array, as_list, as_multiset, as_set, attributes, boolean, box, cbox, curve, curves, dataframe, dataseries, default, default, dummyvariable, equal, evala, evalc, expand, false, float, function, function_bounds, function_curve, function_shells, greater_equal, greater_than, in_convex_polygon, indef_int, interval, less_equal, less_than, list, listlist, matrix, member, multiset, neighborhood, neighbourhood, normal, permute_elements, plot, plot3d, plot_distance, plotthing_compile_result, polynom, procedure, ptbox, range, rational, record, relation, reverse, rifset, rifsimp, rtable, set, sign, simplify, sublist, `subset`, subtype, superlist, superset, supertype, symbol, table, table_indices, testeq, text, true, truefalse, type, undefined, units, vector, verifyfunc, wildcard, xmltree, xvm]

Download VerificationTools_blogpost.mw

Austin Roche
Software Architect
Mathematical Software
Maplesoft

Circles inscribed between curves can be specified by a system of equations relative to the coordinates of the center of the circle and the coordinates of the tangent points. Such a system can have 5 or 6 equations and 6 variables, which are mentioned above.
In the case of 5 equations, we can immediately obtain an infinite set of solutions by selecting the ones we need from it. 
(See the attached text for more details.)
The 1st equation is responsible for the belonging of the point of tangency to one of the curves.
The 2nd equation is responsible for the belonging of the point of tangency to another curve.
In the 3rd equation, the points of tangency on the curves belong to the inscribed circle.
In the 4th and 5th equations, the condition is satisfied that the tangents to the curves are perpendicular to the radii of the circle at the points of contact.
The 6th equation serves either to find a specific inscribed circle or to find an infinite set of solutions. It is selected based on the type of curves and their mutual arrangement.

In this example, we search for a subset of the solution set using the Draghilev method by solving the first five equations of the system: we inscribe circles in two "angles" formed by the intersection of the exponent and the ellipse.
The text of this example, its solution in the form of a picture,"big" option and pictures of similar examples.

INSCRIBED_CIRCLES.mw


 


Addition 09/01/24, 
One curve for the first two equations in coordinates x1,x2 and x3,x4
f1:=
 x1^2 - 2.5*x1*x2 + 3*x2^2 - 1;
f2:=
 x3^2 - 2.5*x3*x4 + 3*x4^2 - 1;

2 3 4 5 6 7 8 Last Page 4 of 76