Joe Riel

9470 Reputation

23 Badges

18 years, 64 days

MaplePrimes Activity

These are answers submitted by Joe Riel

It's not clear to me what you are attempting to do, but the implementation isn't going to work.  Here's why.

The voltage at the non-inverting input of the lower op-amp (probe1) is 0.3V.  For the op-amp to be in the linear region, the inverting input (probe 2) should be at that same voltage (0.3V).

The voltage at the non-inverting input of the upper op-amp is 0.5V. So the voltage at the inverting input should be 0.5V. So the highest voltage attainable at probe 2 (assuming mosfet had zero resistance) is  0.5V*R4/(R4+R5) = 0.5V/11 < 0.05V < 0.3V.  There is no chance that the lower op-amp is in the linear region. 

Thomas Richard's answer is the right one.  Another point; that design isn't going to work (I haven't actually tried to simulate it); there is a problem when switch1 is open as the constant current source has nowhere to go.  A crude solution would be to add a diode clamp to a voltage source greater than the fully charged battery.  Better would be to use a signal current source, turning it on to charge and off when the battery is sufficiently charged. 

The error message is giving you a useful hint.  Change to a stiff solver:  click the "wrench" on the right vertical toolbar and select "Rosenbrock" from the Solver menu.

There are two other relevant issues.  First, the output resistor (R3) has its default value, 1ohm, which is rather low for a typical op-amp. Pick a more reasonable value, say at least 1K.  Second, the op-amp needs a negative rail; in the given model the negative rail input (m) is grounded.  Connect it to, say, -10V.  That will allow the circuit to work properly during the blocking phase.

As C_R suggests, you can use the ideal opamp here.  If you don't care about the op-amp characteristics (say effects of limited bandwidth, output impedance, etc) that is frequently the way to go if it works, however, it won't work in all circuits.  The ideal op-amp merely enforces a virtual ground between its two inputs; it won't work in a switching circuit (say as a comparator).

The circuit is missing a positive bias for the drain of MNMOS2 so that circuit would never perform properly. Also, the two NMOS devices are missing model card parameters.  Alas, fixing those issues won't help here; the mos devices from the SPICE3 library don't work particularly well in MapleSim.  You can model this using the standard mos devices, see current_mirror2.msim, in which I added slightly mismatched resistors and a supply with a ripple voltage so that you can see some mismatch in the currents.

Use unapply.

b := unapply(a(x)+x^2, x);

An alternative approach is just use expressions:

a := x + 1:
b := a + x^2:
a := x + 5:

To evaluate, say, b at x = 3 you could do

eval(b, x=3);


There is more here than meets the eye.  Here's a modification that suggests what is happening:

(**) f := proc(n)
(**) option remember;
(**)     if n < 2 then 1;
(**)     else
(**)         f(n - 1) + f(n - 2);
(**)     end if;
(**) end proc:
(**) F := Compiler:-Compile(f):
Warning, the function names {f} are not recognized in the target language
(**) unassign('f');
(**) F(10);
Error, (in F) number expected for float[8] parameter, got f(9)

Note my use of unassign.  The compiler warning is a hint.  If the unassign is removed, then F(10) returns the correct answer, but only because it is evaluating f in Maple.  To allow recursion to work you can replace the calls to f with thisproc:

(**) f := proc(n)
(**)     if n < 2 then 1;
(**)     else
(**)         thisproc(n - 1) + thisproc(n - 2);
(**)     end if;
(**) end proc:
(**) F := Compiler:-Compile(f):
(**) F(10);


I'm not sure what you are actually looking to achieve.  I believe the custom component shown in the video was created using Modelica Code Editor, which allows more functionality then the Custom Component app, however, you can use a boolean parameter (which is what the solution parameter appears to be) in the Custom Component app to select a branch of a piecewise.  For example

eq := [ diff(x(t),t) = %piecewise(b, sin(t), cost(t)) ]; 

In the app, set the b parameter to type Boolean. It will then appear as a checkbox in the parameter panel of the generated component.

You defined the force on the mass as -9.81*m, where m is a parameter.  However, you didn't assign the mass (SM1) the parameter m, so the force doesn't correspond to gravitional acceleration.  Also, the the mass-with-stop-and-friction component has additional mass not accounted for in the force model.  

If you use the multibody mass component, it will, by default, have the downward acceleration of Earth's gravitional force applied to it.  Then you won't need the external force component. I've uploaded a modified version.  It doesn't include stops.


If you first execute stoperror(traperror), the debugger will open at the occurrence of the assertion that causes the issue.  The library code contains

                  dz1 := numer(normal(diff(z1,x)));
                  ASSERT( degree(dz1,sol) = 1 );
                  dz1 := normal( -coeff(dz1,sol,0) / coeff(dz1,sol) );

but at that point z1 is _X000001+exp(x^2)*exp(-x^2), so dz1 is 0 and the assertion fails.  With assertlevel=2, the ASSERT command raises the error, otherwise the subsequent statement raises a division by zero error.

For this I generally use one of the following techniques

(**) eqs := [1=a,2=b]:
(**) map(rhs=lhs,eqs);
                             [a = 1, b = 2]

(**) (rhs=lhs)~(eqs);
                             [a = 1, b = 2]


A straightforrward method is to eliminate t_y from the objective, and check stationary points:

obj := rho*ln((-beta*tau + rho)/(1 + t__x)) + sigma*ln(sigma/(1 + t__y)) + beta*tau + B - rho - sigma - beta*tau*ln((-beta*tau + rho)/(1 + t__x));
cons := -t__x*(-beta*tau + rho)/(1 + t__x) + t__y*sigma/(1 + t__y) = R:

sol_ty := solve(cons, {t__y});
obj2 := subs(sol_ty, obj);
sol_tx := solve(diff(obj2,t__x), {t__x});
simplify(subs(sol_tx, obj2));

You can also use Lagrange multipliers,

Student:-MultivariateCalculus:-LagrangeMultipliers(obj, [(lhs-rhs)(cons)], [t__x, t__y], 'output = detailed');
[t__x = -(R-2*sigma)/(-beta*tau+R+rho-sigma), 
 t__y = -(-2*beta*tau+R+2*rho)/(-beta*tau+R+rho-sigma), 
 lambda[1] = -(beta*tau-rho-sigma)/(-beta*tau+R+rho-sigma), 
 rho*ln((-beta*tau+rho)/(1+t__x))+sigma*ln(sigma/(1+t__y))+beta*tau+B-rho-sigma-beta*tau*ln((-beta*tau+rho)/(1+t__x)) = rho*ln((-beta*tau+rho)/(1-(R-2*sigma)/(-beta*tau+R+rho-sigma)))+sigma*ln(sigma/(1-(-2*beta*tau+R+2*rho)/(-beta*tau+R+rho-sigma)))+beta*tau+B-rho-sigma-beta*tau*ln((-beta*tau+rho)/(1-(R-2*sigma)/(-beta*tau+R+rho-sigma)))


Doing directly what you want isn't feasible in that the file is not syntactically valid Maple input.  A workaround is to use strings to assign the differential equations of interest, then parse them into the correponding Maple expression.

Maple doesn't directly provide a parser for its 2D input. Here's a hackish approach.  No implications that this is robust. 

ParsePrimes := proc(str :: string, indep :: symbol := 'x')
local b, p, pos, primes, s, var, vars;
uses ST = StringTools;
    b := ST:-StringBuffer();
    vars := MutableSet();
    s := str;
    while ST:-RegMatch("([A-Za-z_]+)('+)"
                       , s
                       , 'all', 'var', 'primes'
                      ) do
        pos := SearchText(all, s);
        b:-appendf("diff(%s(x),[x$%d])", var, length(primes));
        s := s[pos+length(all)..-1];
        vars ,= parse(var);
    end do;
    s := b:-value();

    p := parse(s);

    # Ensure non-primed dependent variables are converted to functions
    # of the independent variable

    if numelems(vars) > 0 then
        p := subsindets(p, 'identical'(seq(vars)), y -> y(indep));
    end if;


end proc:

# assign a short function name 
`_` := ParsePrimes:

z := _("3*y''+2*y'+y");

                 z := 3*diff(y(x),x $ 2)+2*diff(y(x),x)+y(x)


Here's another confirmation, using Syrup:

resistance := proc( n :: posint := 2 )
local G, ckt, edge, i, sbuf, sol;
uses GT = GraphTheory;
    sbuf := StringTools:-StringBuffer();
    sbuf:-append("* Soccer Ball *\n");
    G := GT:-SpecialGraphs:-SoccerBallGraph();
    for i,edge in GT:-Edges(G) do
        sbuf:-appendf("R%d %d %d 1\n", i, op(edge));
    end do;
    sbuf:-append("V0 1 0 0\n");       # ground vertex 1
    sbuf:-appendf("I0 0 %d 1\n", n);  # connect 1 A to vertex n
    ckt := sbuf:-value();
    sol := Syrup:-Solve(ckt, 'dc');
    eval('v'[n], sol);
end proc:



The frame_c port of the box component (by default shown on the bottom) is vectorized.  Each connection to it can connect to a different additional frame.  To select the desired additional frame, make a connection, then select the "wire" and select the desired frame from the drop-down menu that will appear in the upper right pane (the connector inspector).  When connecting a "scalar" port to a vectorized port you will get a pop-up warning indicating the two have different dimensions; that's a cue to use the connector inspector.

I've attached the modified msim.

As others have posted, there are shorter ways to do this, but they don't necessarily generalize; some times you need to use nested loops.  You can do that with

x := [1,2,3,4]:    # x is a list, not a Vector
k := Matrix(4,4):  # Assign k a 4x4 Matrix; by default it is initialized with all zeros.
for i to 4 do      # By default, Maple for loops start at 1
    for j from 1 to 4 do  # Here's notation for explicitly starting from 1
       k[i,j] := x[i] + x[j];
    end do;
end do:


3 4 5 6 7 8 9 Last Page 5 of 113